@woosh/meep-engine 2.124.11 → 2.124.12

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 (38) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/core/assert.d.ts +8 -0
  4. package/src/core/assert.d.ts.map +1 -1
  5. package/src/core/assert.js +14 -0
  6. package/src/core/debug/matchers/IsFinite.d.ts +6 -0
  7. package/src/core/debug/matchers/IsFinite.d.ts.map +1 -0
  8. package/src/core/debug/matchers/IsFinite.js +11 -0
  9. package/src/core/debug/matchers/IsInteger.d.ts +6 -0
  10. package/src/core/debug/matchers/IsInteger.d.ts.map +1 -0
  11. package/src/core/debug/matchers/IsInteger.js +11 -0
  12. package/src/core/debug/matchers/IsUndefined.js +1 -0
  13. package/src/core/debug/matchers/matchers.d.ts +5 -0
  14. package/src/core/debug/matchers/matchers.d.ts.map +1 -1
  15. package/src/core/debug/matchers/matchers.js +14 -0
  16. package/src/core/math/interval/NumericInterval.d.ts +49 -9
  17. package/src/core/math/interval/NumericInterval.d.ts.map +1 -1
  18. package/src/core/math/interval/NumericInterval.js +91 -13
  19. package/src/core/math/spline/spline_hermite3_bounds.d.ts +7 -7
  20. package/src/core/math/spline/spline_hermite3_bounds.d.ts.map +1 -1
  21. package/src/core/math/spline/spline_hermite3_bounds.js +13 -7
  22. package/src/core/model/ObservedBoolean.d.ts +3 -3
  23. package/src/core/model/ObservedBoolean.d.ts.map +1 -1
  24. package/src/core/model/ObservedBoolean.js +3 -3
  25. package/src/core/model/ObservedEnum.d.ts.map +1 -1
  26. package/src/core/model/ObservedEnum.js +52 -11
  27. package/src/core/model/ObservedInteger.d.ts +7 -7
  28. package/src/core/model/ObservedInteger.d.ts.map +1 -1
  29. package/src/core/model/ObservedInteger.js +12 -11
  30. package/src/engine/animation/curve/AnimationCurve.d.ts +12 -6
  31. package/src/engine/animation/curve/AnimationCurve.d.ts.map +1 -1
  32. package/src/engine/animation/curve/AnimationCurve.js +27 -15
  33. package/src/engine/animation/curve/animation_curve_compute_aabb.js +1 -1
  34. package/src/engine/animation/curve/animation_curve_optimize.d.ts +2 -1
  35. package/src/engine/animation/curve/animation_curve_optimize.d.ts.map +1 -1
  36. package/src/engine/animation/curve/animation_curve_optimize.js +6 -0
  37. package/src/engine/ecs/EntityComponentDataset.d.ts.map +1 -1
  38. package/src/engine/ecs/EntityComponentDataset.js +20 -7
package/README.md CHANGED
@@ -13,7 +13,7 @@ To help get you started, various samples are provided under `/samples` folder. F
13
13
 
14
14
  ## Quality
15
15
 
16
- Meep is covered by 2,508 unit tests
16
+ Meep is covered by 2,669 unit tests
17
17
 
18
18
  The aim is to [ensure quality](https://about.codecov.io/blog/the-case-against-100-code-coverage/). As a result, the tests are written to cover complex code first and to exhaustively validate critical algorithms.
19
19
  Most of the test code is significantly larger than the code that is being tested.
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Pure JavaScript game engine. Fully featured and production ready.",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.124.11",
8
+ "version": "2.124.12",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -128,6 +128,14 @@ export namespace assert {
128
128
  import isFiniteNumber = isFinite;
129
129
  export { isFiniteNumber };
130
130
  /**
131
+ * More powerful and flexible assertion API based on matchers.
132
+ * Allows complex matching criteria to be constructed.
133
+ *
134
+ * see {@link Matcher}
135
+ * @example
136
+ * assert.that(value,'value', anyOf(isNull(),isUndefined())); // will trigger iff !(value === undefined || value === null)
137
+ * assert.that(value, 'value', isOneOf([3,7])); // will only trigger iff !(value === 3 || value === 7)
138
+ *
131
139
  * @template T
132
140
  * @param {T} value
133
141
  * @param {string} name
@@ -1 +1 @@
1
- {"version":3,"file":"assert.d.ts","sourceRoot":"","sources":["../../../src/core/assert.js"],"names":[],"mappings":"AAgDA;;;;GAIG;AACH,0BAHW,OAAO,MACP,MAAM,QAMhB;;IAsJD;;;;;OAKG;IACH,eALa,CAAC,SACH,CAAC,0BAED,MAAM,QAUhB;;;;;;;;;;;;;;;IAmBD;;;;;;OAMG;IACH,oCALW,GAAC,SACD,KAAK,eACL,MAAM,eACN,MAAM,QAKhB;IAGD;;;;OAIG;IACH,gCAHW,MAAM,GAAC,GAAC,SACR,MAAM,QAQhB;IAED;;;;OAIG;IACH,gCAHW,MAAM,GAAC,GAAC,SACR,MAAM,QAQhB;IAED;;;;OAIG;IACH,iCAHW,OAAO,GAAC,GAAC,SACT,MAAM,QAQhB;IAED;;;;OAIG;IACH,kCAHW,WAAS,GAAC,SACV,MAAM,QAQhB;IAED;;;;OAIG;IACH,gCAHW,MAAO,GAAC,SACR,MAAM,QAQhB;IAED;;;;OAIG;IACH,iCAHW,MAAM,GAAC,GAAC,SACR,MAAM,QAQhB;IAED;;;;OAIG;IACH,4CAHW,MAAM,GAAC,GAAC,SACR,MAAM,QAQhB;IAED;;;;OAIG;IACH,wBAJa,CAAC,SACH,CAAC,EAAE,SACH,MAAM,QAOhB;IAED;;;;OAIG;IACH,4BAJa,CAAC,SACH,SAAS,CAAC,CAAC,CAAC,GAAC,CAAC,EAAE,GAAC,WAAW,GAAC,YAAY,SACzC,MAAM,QAOhB;IAGD;;;;OAIG;IACH,+BAHW,GAAC,uBASX;IAED;;;;OAIG;IACH,iCAHW,GAAC,uBASX;IAGD;;;;OAIG;IACH,8BAHW,GAAC,uBAOX;IAED;;;;OAIG;IACH,+BAHW,GAAC,uBASX;IAED;;;;OAIG;IACH,8BAHW,MAAM,SACN,MAAM,QAMhB;IAED;;;;;OAKG;IACH,gCAHW,MAAM,SACN,MAAM,QAMhB;;;IAQD;;;;;OAKG;IACH,qBALa,CAAC,SACH,CAAC,QACD,MAAM,WACN,OAAO,CAAC,CAAC,CAAC,QAkBpB;;AApcD;;;;;GAKG;AACH,0BALa,CAAC,KACH,CAAC,KACD,CAAC,MACD,MAAM,QAIhB;AAED;;;;GAIG;AACH,0BAHW,OAAO,MACP,MAAM,QAIhB;AAhCD;;;;;GAKG;AACH,uBALa,CAAC,KACH,CAAC,KACD,CAAC,MACD,MAAM,QAShB;AAqBD;;;;;GAKG;AACH,kCAJW,MAAM,KACN,MAAM,MACN,MAAM,QAIhB;AAaD;;;;;GAKG;AACH,gCAJW,MAAM,KACN,MAAM,MACN,MAAM,QAiBhB;AAyBD;;;;;GAKG;AACH,uCAJW,MAAM,KACN,MAAM,MACN,MAAM,QAiBhB;AA5CD;;;;;GAKG;AACH,6BAJW,MAAM,KACN,MAAM,MACN,MAAM,QAiBhB;AAyBD;;;;;GAKG;AACH,oCAJW,MAAM,KACN,MAAM,MACN,MAAM,QAiBhB;AAKD;;;;;GAKG;AACH,+BAJW,GAAC,QACD,MAAM,cACN,MAAM,QAehB;AAED;;;;;GAKG;AACH,0BALa,CAAC,YACH,CAAC,EAAE,UACH,CAAC,YACD,MAAM,QAIhB;AAED;;;;;GAKG;AACH,4BALa,CAAC,YACH,CAAC,EAAE,UACH,CAAC,YACD,MAAM,QAIhB;AAED;;;;;GAKG;AACH,4BALa,CAAC,KACH,CAAC,EAAE,GAAC,SAAS,CAAC,CAAC,CAAC,GAAC,YAAY,GAAC,UAAU,KACxC,CAAC,EAAE,GAAC,SAAS,CAAC,CAAC,CAAC,GAAC,YAAY,GAAC,UAAU,YACxC,MAAM,QAMhB"}
1
+ {"version":3,"file":"assert.d.ts","sourceRoot":"","sources":["../../../src/core/assert.js"],"names":[],"mappings":"AAgDA;;;;GAIG;AACH,0BAHW,OAAO,MACP,MAAM,QAMhB;;IAsJD;;;;;OAKG;IACH,eALa,CAAC,SACH,CAAC,0BAED,MAAM,QAUhB;;;;;;;;;;;;;;;IAmBD;;;;;;OAMG;IACH,oCALW,GAAC,SACD,KAAK,eACL,MAAM,eACN,MAAM,QAKhB;IAGD;;;;OAIG;IACH,gCAHW,MAAM,GAAC,GAAC,SACR,MAAM,QAQhB;IAED;;;;OAIG;IACH,gCAHW,MAAM,GAAC,GAAC,SACR,MAAM,QAQhB;IAED;;;;OAIG;IACH,iCAHW,OAAO,GAAC,GAAC,SACT,MAAM,QAQhB;IAED;;;;OAIG;IACH,kCAHW,WAAS,GAAC,SACV,MAAM,QAQhB;IAED;;;;OAIG;IACH,gCAHW,MAAO,GAAC,SACR,MAAM,QAQhB;IAED;;;;OAIG;IACH,iCAHW,MAAM,GAAC,GAAC,SACR,MAAM,QAQhB;IAED;;;;OAIG;IACH,4CAHW,MAAM,GAAC,GAAC,SACR,MAAM,QAQhB;IAED;;;;OAIG;IACH,wBAJa,CAAC,SACH,CAAC,EAAE,SACH,MAAM,QAOhB;IAED;;;;OAIG;IACH,4BAJa,CAAC,SACH,SAAS,CAAC,CAAC,CAAC,GAAC,CAAC,EAAE,GAAC,WAAW,GAAC,YAAY,SACzC,MAAM,QAOhB;IAGD;;;;OAIG;IACH,+BAHW,GAAC,uBASX;IAED;;;;OAIG;IACH,iCAHW,GAAC,uBASX;IAGD;;;;OAIG;IACH,8BAHW,GAAC,uBAOX;IAED;;;;OAIG;IACH,+BAHW,GAAC,uBASX;IAED;;;;OAIG;IACH,8BAHW,MAAM,SACN,MAAM,QAMhB;IAED;;;;;OAKG;IACH,gCAHW,MAAM,SACN,MAAM,QAMhB;;;IAQD;;;;;;;;;;;;;OAaG;IACH,qBALa,CAAC,SACH,CAAC,QACD,MAAM,WACN,OAAO,CAAC,CAAC,CAAC,QAwBpB;;AAldD;;;;;GAKG;AACH,0BALa,CAAC,KACH,CAAC,KACD,CAAC,MACD,MAAM,QAIhB;AAED;;;;GAIG;AACH,0BAHW,OAAO,MACP,MAAM,QAIhB;AAhCD;;;;;GAKG;AACH,uBALa,CAAC,KACH,CAAC,KACD,CAAC,MACD,MAAM,QAShB;AAqBD;;;;;GAKG;AACH,kCAJW,MAAM,KACN,MAAM,MACN,MAAM,QAIhB;AAaD;;;;;GAKG;AACH,gCAJW,MAAM,KACN,MAAM,MACN,MAAM,QAiBhB;AAyBD;;;;;GAKG;AACH,uCAJW,MAAM,KACN,MAAM,MACN,MAAM,QAiBhB;AA5CD;;;;;GAKG;AACH,6BAJW,MAAM,KACN,MAAM,MACN,MAAM,QAiBhB;AAyBD;;;;;GAKG;AACH,oCAJW,MAAM,KACN,MAAM,MACN,MAAM,QAiBhB;AAKD;;;;;GAKG;AACH,+BAJW,GAAC,QACD,MAAM,cACN,MAAM,QAehB;AAED;;;;;GAKG;AACH,0BALa,CAAC,YACH,CAAC,EAAE,UACH,CAAC,YACD,MAAM,QAIhB;AAED;;;;;GAKG;AACH,4BALa,CAAC,YACH,CAAC,EAAE,UACH,CAAC,YACD,MAAM,QAIhB;AAED;;;;;GAKG;AACH,4BALa,CAAC,KACH,CAAC,EAAE,GAAC,SAAS,CAAC,CAAC,CAAC,GAAC,YAAY,GAAC,UAAU,KACxC,CAAC,EAAE,GAAC,SAAS,CAAC,CAAC,CAAC,GAAC,YAAY,GAAC,UAAU,YACxC,MAAM,QAMhB"}
@@ -448,16 +448,30 @@ assert.isFinite = function (value, name = "value") {
448
448
  assert.isFiniteNumber = assert.isFinite;
449
449
 
450
450
  /**
451
+ * More powerful and flexible assertion API based on matchers.
452
+ * Allows complex matching criteria to be constructed.
453
+ *
454
+ * see {@link Matcher}
455
+ * @example
456
+ * assert.that(value,'value', anyOf(isNull(),isUndefined())); // will trigger iff !(value === undefined || value === null)
457
+ * assert.that(value, 'value', isOneOf([3,7])); // will only trigger iff !(value === 3 || value === 7)
458
+ *
451
459
  * @template T
452
460
  * @param {T} value
453
461
  * @param {string} name
454
462
  * @param {Matcher<T>} matcher
455
463
  */
456
464
  assert.that = function (value, name, matcher) {
465
+ assert.isString(name, 'name');
466
+ assert.defined(matcher, 'matcher');
467
+
457
468
  if (matcher.matches(value)) {
458
469
  return;
459
470
  }
460
471
 
472
+ // if we got here, our assertion has failed
473
+ // construct failure message
474
+
461
475
  const mismatch_description = new InMemoryDescriptor();
462
476
 
463
477
  mismatch_description.appendText(`Expected ${name} to be `);
@@ -0,0 +1,6 @@
1
+ export class IsFinite extends BaseMatcher {
2
+ matches(item: any, mismatch_description: any): boolean;
3
+ describeTo(description: any): void;
4
+ }
5
+ import { BaseMatcher } from "../BaseMatcher.js";
6
+ //# sourceMappingURL=IsFinite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IsFinite.d.ts","sourceRoot":"","sources":["../../../../../src/core/debug/matchers/IsFinite.js"],"names":[],"mappings":"AAEA;IACI,uDAEC;IAED,mCAEC;CACJ;4BAV2B,mBAAmB"}
@@ -0,0 +1,11 @@
1
+ import { BaseMatcher } from "../BaseMatcher.js";
2
+
3
+ export class IsFinite extends BaseMatcher {
4
+ matches(item, mismatch_description) {
5
+ return Number.isFinite(item);
6
+ }
7
+
8
+ describeTo(description) {
9
+ description.appendText("finite");
10
+ }
11
+ }
@@ -0,0 +1,6 @@
1
+ export class IsInteger extends BaseMatcher {
2
+ matches(item: any, mismatch_description: any): boolean;
3
+ describeTo(description: any): void;
4
+ }
5
+ import { BaseMatcher } from "../BaseMatcher.js";
6
+ //# sourceMappingURL=IsInteger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IsInteger.d.ts","sourceRoot":"","sources":["../../../../../src/core/debug/matchers/IsInteger.js"],"names":[],"mappings":"AAEA;IACI,uDAEC;IAED,mCAEC;CACJ;4BAV2B,mBAAmB"}
@@ -0,0 +1,11 @@
1
+ import { BaseMatcher } from "../BaseMatcher.js";
2
+
3
+ export class IsInteger extends BaseMatcher {
4
+ matches(item, mismatch_description) {
5
+ return Number.isInteger(item);
6
+ }
7
+
8
+ describeTo(description) {
9
+ description.appendText("integer");
10
+ }
11
+ }
@@ -9,3 +9,4 @@ export class IsUndefined extends BaseMatcher {
9
9
  description.appendText("undefined");
10
10
  }
11
11
  }
12
+
@@ -48,6 +48,9 @@ export function isUndefined<T_1>(): Matcher<T_1>;
48
48
  * @return {Matcher<T>}
49
49
  */
50
50
  export function isDefined<T_1>(): Matcher<T_1>;
51
+ export function isFinite(): IsFinite;
52
+ export function isInfinite(): Matcher<any>;
53
+ export function isInteger(): IsInteger;
51
54
  /**
52
55
  * @template T
53
56
  * @param {Matcher|T} value
@@ -85,4 +88,6 @@ export function nothing<T_1>(message?: string): Matcher<T_1>;
85
88
  */
86
89
  export function isNotUndefined<T_1>(): Matcher<T_1>;
87
90
  import { Matcher } from "../Matcher.js";
91
+ import { IsFinite } from "./IsFinite.js";
92
+ import { IsInteger } from "./IsInteger.js";
88
93
  //# sourceMappingURL=matchers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../../../../src/core/debug/matchers/matchers.js"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,wCAHW,OAAO,CAAC,GAAC,CAAC,GACT,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;;GAIG;AACH,wCAHW,OAAO,CAAC,GAAC,CAAC,GACT,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;;GAIG;AACH,kCAHW,OAAO,CAAC,GAAC,CAAC,GACT,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;;GAIG;AACH,oCAHW,GAAC,GACA,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;;GAIG;AACH,uCAHW,GAAC,GACA,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;GAGG;AACH,+BAFY,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;GAGG;AACH,kCAFY,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;GAGG;AACH,oCAFY,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;GAGG;AACH,kCAFY,OAAO,CAAC,GAAC,CAAC,CAIrB;AAQD;;;;GAIG;AACH,oCAHW,eAAQ,GAAC,GACR,OAAO,CAAC,GAAC,CAAC,CAQrB;AAED;;;;GAIG;AACH,iCAHW,GAAC,EAAE,GACD,OAAO,CAAC,GAAC,CAAC,CAItB;AAGD;;;;GAIG;AACH,0CAHW,GAAC,GACA,OAAO,CAAC,GAAC,CAAC,CAIrB;AAcD;;;;;GAKG;AACH,wCAHW,MAAM,GACL,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;;GAIG;AACH,uCAHW,MAAM,GACL,OAAO,CAAC,GAAC,CAAC,CAUrB;AAjFD;;;GAGG;AACH,uCAFY,OAAO,CAAC,GAAC,CAAC,CAIrB;wBAvFuB,eAAe"}
1
+ {"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../../../../src/core/debug/matchers/matchers.js"],"names":[],"mappings":"AAcA;;;;GAIG;AACH,wCAHW,OAAO,CAAC,GAAC,CAAC,GACT,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;;GAIG;AACH,wCAHW,OAAO,CAAC,GAAC,CAAC,GACT,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;;GAIG;AACH,kCAHW,OAAO,CAAC,GAAC,CAAC,GACT,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;;GAIG;AACH,oCAHW,GAAC,GACA,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;;GAIG;AACH,uCAHW,GAAC,GACA,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;GAGG;AACH,+BAFY,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;GAGG;AACH,kCAFY,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;GAGG;AACH,oCAFY,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;GAGG;AACH,kCAFY,OAAO,CAAC,GAAC,CAAC,CAIrB;AAQD,qCAEC;AAED,2CAEC;AAED,uCAEC;AAED;;;;GAIG;AACH,oCAHW,eAAQ,GAAC,GACR,OAAO,CAAC,GAAC,CAAC,CAQrB;AAED;;;;GAIG;AACH,iCAHW,GAAC,EAAE,GACD,OAAO,CAAC,GAAC,CAAC,CAItB;AAGD;;;;GAIG;AACH,0CAHW,GAAC,GACA,OAAO,CAAC,GAAC,CAAC,CAIrB;AAcD;;;;;GAKG;AACH,wCAHW,MAAM,GACL,OAAO,CAAC,GAAC,CAAC,CAIrB;AAED;;;;GAIG;AACH,uCAHW,MAAM,GACL,OAAO,CAAC,GAAC,CAAC,CAUrB;AA7FD;;;GAGG;AACH,uCAFY,OAAO,CAAC,GAAC,CAAC,CAIrB;wBAzFuB,eAAe;yBAMd,eAAe;0BAEd,gBAAgB"}
@@ -4,7 +4,9 @@ import { AnyOf } from "./AnyOf.js";
4
4
  import { DescribeAs } from "./DescribeAs.js";
5
5
  import { IsAnything } from "./IsAnything.js";
6
6
  import { IsEqual } from "./IsEqual.js";
7
+ import { IsFinite } from "./IsFinite.js";
7
8
  import { IsIn } from "./IsIn.js";
9
+ import { IsInteger } from "./IsInteger.js";
8
10
  import { IsIterableContaining } from "./IsIterableContaining.js";
9
11
  import { IsNot } from "./IsNot.js";
10
12
  import { IsNull } from "./IsNull.js";
@@ -93,6 +95,18 @@ export function isDefined() {
93
95
  */
94
96
  export const isNotUndefined = isDefined;
95
97
 
98
+ export function isFinite(){
99
+ return new IsFinite();
100
+ }
101
+
102
+ export function isInfinite(){
103
+ return not(isFinite());
104
+ }
105
+
106
+ export function isInteger(){
107
+ return new IsInteger();
108
+ }
109
+
96
110
  /**
97
111
  * @template T
98
112
  * @param {Matcher|T} value
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Defines a numeric interval, by min and max.
3
+ * Provides a suite of interval logic operations.
4
+ * Interval can be of 0 width.
5
+ */
1
6
  export class NumericInterval {
2
7
  /**
3
8
  *
@@ -25,13 +30,15 @@ export class NumericInterval {
25
30
  *
26
31
  * @param {number} min
27
32
  * @param {number} max
33
+ * @returns {this}
28
34
  */
29
- set(min: number, max: number): void;
35
+ set(min: number, max: number): this;
30
36
  /**
31
37
  *
32
38
  * @param {number} value
39
+ * @returns {this}
33
40
  */
34
- multiplyScalar(value: number): void;
41
+ multiplyScalar(value: number): this;
35
42
  /**
36
43
  * Compute normalized position of input within this interval, where result is 0 if input is equal to `min`, and 1 when input is equal to `max`
37
44
  * @param {number} v value to be normalized
@@ -49,11 +56,6 @@ export class NumericInterval {
49
56
  * @returns {boolean}
50
57
  */
51
58
  isExact(): boolean;
52
- /**
53
- *
54
- * @returns {number}
55
- */
56
- computeAverage(): number;
57
59
  /**
58
60
  *
59
61
  * @param {function} random Random number generator function, must return values between 0 and 1
@@ -65,6 +67,19 @@ export class NumericInterval {
65
67
  min: number;
66
68
  max: number;
67
69
  };
70
+ /**
71
+ *
72
+ * @param {number[]|Float32Array|Float64Array} array
73
+ * @param {number} [offset=0]
74
+ */
75
+ fromArray(array: number[] | Float32Array | Float64Array, offset?: number): this;
76
+ /**
77
+ *
78
+ * @param {number[]|Float32Array|Float64Array} [destination=[]]
79
+ * @param {number} [offset=0]
80
+ * @return {number[]}
81
+ */
82
+ toArray(destination?: number[] | Float32Array | Float64Array, offset?: number): number[];
68
83
  toString(): string;
69
84
  /**
70
85
  *
@@ -79,8 +94,27 @@ export class NumericInterval {
79
94
  /**
80
95
  *
81
96
  * @param {NumericInterval} other
97
+ * @returns {this}
98
+ */
99
+ copy(other: NumericInterval): this;
100
+ /**
101
+ * Performs union operation with another interval, mutates current interval.
102
+ * @param {NumericInterval} other
103
+ * @returns {this}
104
+ */
105
+ union(other: NumericInterval): this;
106
+ /**
107
+ *
108
+ * @param {NumericInterval} other
109
+ * @return {boolean}
82
110
  */
83
- copy(other: NumericInterval): void;
111
+ overlaps(other: NumericInterval): boolean;
112
+ /**
113
+ *
114
+ * @param {NumericInterval} other
115
+ * @return {boolean}
116
+ */
117
+ contains(other: NumericInterval): boolean;
84
118
  /**
85
119
  *
86
120
  * @param {NumericInterval} other
@@ -93,10 +127,16 @@ export class NumericInterval {
93
127
  */
94
128
  hash(): number;
95
129
  /**
96
- * Distance between min and max (= max - min)
130
+ * Distance between min and max (`= max - min`)
97
131
  * @returns {number}
98
132
  */
99
133
  get span(): number;
134
+ get middle(): number;
135
+ /**
136
+ * @deprecated use {@link middle} instead
137
+ * @returns {number}
138
+ */
139
+ computeAverage(): number;
100
140
  /**
101
141
  * @readonly
102
142
  * @type {boolean}
@@ -1 +1 @@
1
- {"version":3,"file":"NumericInterval.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/interval/NumericInterval.js"],"names":[],"mappings":"AAKA;IACI;;;;;OAKG;IACH,kBAJW,MAAM,QACN,MAAM,EA4BhB;IAhBG;;;OAGG;IACH,KAFU,MAAM,CAEF;IACd;;;OAGG;IACH,KAFU,MAAM,CAEF;IAEd;;;OAGG;IACH,oBAFU,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAEnB;IAIjC;;;;OAIG;IACH,SAHW,MAAM,OACN,MAAM,QA0BhB;IAGD;;;OAGG;IACH,sBAFW,MAAM,QAahB;IAED;;;;OAIG;IACH,kBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,UAFa,OAAO,CAInB;IAED;;;;OAIG;IACH,WAFa,OAAO,CAInB;IAED;;;OAGG;IACH,kBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,gCAFa,MAAM,CAMlB;IAED,0BAEC;IAED;;;MAKC;IAED,mBAEC;IAED;;;OAGG;IACH,uBAFW,YAAY,QAKtB;IAED;;;OAGG;IACH,yBAFW,YAAY,QAKtB;IAED;;;OAGG;IACH,YAFW,eAAe,QAIzB;IAED;;;;OAIG;IACH,cAHW,eAAe,GACb,OAAO,CAInB;IAED;;;OAGG;IACH,QAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,YAFa,MAAM,CAIlB;IAGL;;;OAGG;IACH,4BAFU,OAAO,CAE0B;CAN1C;;mBAUS,eAAe;kBAMf,eAAe;iBAMf,eAAe;;mBAhON,+BAA+B"}
1
+ {"version":3,"file":"NumericInterval.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/interval/NumericInterval.js"],"names":[],"mappings":"AAKA;;;;GAIG;AACH;IACI;;;;;OAKG;IACH,kBAJW,MAAM,QACN,MAAM,EA4BhB;IAhBG;;;OAGG;IACH,KAFU,MAAM,CAEF;IACd;;;OAGG;IACH,KAFU,MAAM,CAEF;IAEd;;;OAGG;IACH,oBAFU,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAEnB;IAIjC;;;;;OAKG;IACH,SAJW,MAAM,OACN,MAAM,GACJ,IAAI,CA6BhB;IAGD;;;;OAIG;IACH,sBAHW,MAAM,GACJ,IAAI,CAchB;IAED;;;;OAIG;IACH,kBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,UAFa,OAAO,CAInB;IAED;;;;OAIG;IACH,WAFa,OAAO,CAInB;IAGD;;;;OAIG;IACH,gCAFa,MAAM,CAOlB;IAED,0BAEC;IAED;;;MAKC;IAED;;;;OAIG;IACH,iBAHW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,WAClC,MAAM,QAIhB;IAED;;;;;OAKG;IACH,sBAJW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,WAClC,MAAM,GACL,MAAM,EAAE,CAOnB;IAED,mBAEC;IAED;;;OAGG;IACH,uBAFW,YAAY,QAKtB;IAED;;;OAGG;IACH,yBAFW,YAAY,QAKtB;IAED;;;;OAIG;IACH,YAHW,eAAe,GACb,IAAI,CAIhB;IAED;;;;OAIG;IACH,aAHW,eAAe,GACb,IAAI,CAShB;IAED;;;;OAIG;IACH,gBAHW,eAAe,GACd,OAAO,CAMlB;IAED;;;;OAIG;IACH,gBAHW,eAAe,GACd,OAAO,CAMlB;IAED;;;;OAIG;IACH,cAHW,eAAe,GACb,OAAO,CAMnB;IAED;;;OAGG;IACH,QAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,YAFa,MAAM,CAIlB;IAED,qBAEC;IAED;;;OAGG;IACH,kBAFa,MAAM,CAIlB;IAGL;;;OAGG;IACH,4BAFU,OAAO,CAE0B;CAN1C;;mBAUS,eAAe;kBAMf,eAAe;iBAMf,eAAe;;mBA9SN,+BAA+B"}
@@ -3,6 +3,11 @@ import Signal from "../../events/signal/Signal.js";
3
3
  import { computeHashFloat } from "../../primitives/numbers/computeHashFloat.js";
4
4
  import { inverseLerp } from "../inverseLerp.js";
5
5
 
6
+ /**
7
+ * Defines a numeric interval, by min and max.
8
+ * Provides a suite of interval logic operations.
9
+ * Interval can be of 0 width.
10
+ */
6
11
  export class NumericInterval {
7
12
  /**
8
13
  *
@@ -42,6 +47,7 @@ export class NumericInterval {
42
47
  *
43
48
  * @param {number} min
44
49
  * @param {number} max
50
+ * @returns {this}
45
51
  */
46
52
  set(min, max) {
47
53
  assert.isNumber(min, 'min');
@@ -56,23 +62,27 @@ export class NumericInterval {
56
62
  const oldMax = this.max;
57
63
 
58
64
  if (min === oldMin && max === oldMax) {
59
- return;
65
+ // no change
66
+ return this;
60
67
  }
61
68
 
62
69
  this.min = min;
63
70
  this.max = max;
64
71
 
65
72
  if (!this.onChanged.hasHandlers()) {
66
- return;
73
+ return this;
67
74
  }
68
75
 
69
76
  this.onChanged.send4(min, max, oldMin, oldMax);
77
+
78
+ return this;
70
79
  }
71
80
 
72
81
 
73
82
  /**
74
83
  *
75
84
  * @param {number} value
85
+ * @returns {this}
76
86
  */
77
87
  multiplyScalar(value) {
78
88
  const v0 = this.min * value;
@@ -82,9 +92,10 @@ export class NumericInterval {
82
92
  //probably negative scale
83
93
  this.set(v1, v0);
84
94
  } else {
85
-
86
95
  this.set(v0, v1);
87
96
  }
97
+
98
+ return this;
88
99
  }
89
100
 
90
101
  /**
@@ -113,13 +124,6 @@ export class NumericInterval {
113
124
  return this.min === this.max;
114
125
  }
115
126
 
116
- /**
117
- *
118
- * @returns {number}
119
- */
120
- computeAverage() {
121
- return (this.min + this.max) * 0.5;
122
- }
123
127
 
124
128
  /**
125
129
  *
@@ -129,7 +133,8 @@ export class NumericInterval {
129
133
  sampleRandom(random) {
130
134
  assert.isFunction(random, "random");
131
135
 
132
- return this.min + random() * (this.max - this.min);
136
+ const span = this.max - this.min;
137
+ return this.min + random() * span;
133
138
  }
134
139
 
135
140
  fromJSON(json) {
@@ -143,6 +148,28 @@ export class NumericInterval {
143
148
  };
144
149
  }
145
150
 
151
+ /**
152
+ *
153
+ * @param {number[]|Float32Array|Float64Array} array
154
+ * @param {number} [offset=0]
155
+ */
156
+ fromArray(array, offset = 0) {
157
+ return this.set(array[offset], array[offset + 1]);
158
+ }
159
+
160
+ /**
161
+ *
162
+ * @param {number[]|Float32Array|Float64Array} [destination=[]]
163
+ * @param {number} [offset=0]
164
+ * @return {number[]}
165
+ */
166
+ toArray(destination = [], offset = 0) {
167
+ destination[offset] = this.min;
168
+ destination[offset + 1] = this.max;
169
+
170
+ return destination;
171
+ }
172
+
146
173
  toString() {
147
174
  return `NumericInterval{ min=${this.min}, max=${this.max} }`;
148
175
  }
@@ -168,9 +195,46 @@ export class NumericInterval {
168
195
  /**
169
196
  *
170
197
  * @param {NumericInterval} other
198
+ * @returns {this}
171
199
  */
172
200
  copy(other) {
173
- this.set(other.min, other.max);
201
+ return this.set(other.min, other.max);
202
+ }
203
+
204
+ /**
205
+ * Performs union operation with another interval, mutates current interval.
206
+ * @param {NumericInterval} other
207
+ * @returns {this}
208
+ */
209
+ union(other) {
210
+ assert.equal(other.isNumericInterval, true, "other must be a NumericInterval");
211
+
212
+ return this.set(
213
+ Math.min(this.min, other.min),
214
+ Math.max(this.max, other.max)
215
+ );
216
+ }
217
+
218
+ /**
219
+ *
220
+ * @param {NumericInterval} other
221
+ * @return {boolean}
222
+ */
223
+ overlaps(other) {
224
+ assert.equal(other.isNumericInterval, true, "other must be a NumericInterval");
225
+
226
+ return this.min < other.max && this.max > other.min;
227
+ }
228
+
229
+ /**
230
+ *
231
+ * @param {NumericInterval} other
232
+ * @return {boolean}
233
+ */
234
+ contains(other) {
235
+ assert.equal(other.isNumericInterval, true, "other must be a NumericInterval");
236
+
237
+ return this.min <= other.min && this.max >= other.max;
174
238
  }
175
239
 
176
240
  /**
@@ -179,6 +243,8 @@ export class NumericInterval {
179
243
  * @returns {boolean}
180
244
  */
181
245
  equals(other) {
246
+ assert.equal(other.isNumericInterval, true, "other must be a NumericInterval");
247
+
182
248
  return this.min === other.min && this.max === other.max;
183
249
  }
184
250
 
@@ -195,12 +261,24 @@ export class NumericInterval {
195
261
  }
196
262
 
197
263
  /**
198
- * Distance between min and max (= max - min)
264
+ * Distance between min and max (`= max - min`)
199
265
  * @returns {number}
200
266
  */
201
267
  get span() {
202
268
  return this.max - this.min;
203
269
  }
270
+
271
+ get middle() {
272
+ return (this.max + this.min) * 0.5;
273
+ }
274
+
275
+ /**
276
+ * @deprecated use {@link middle} instead
277
+ * @returns {number}
278
+ */
279
+ computeAverage() {
280
+ return this.middle;
281
+ }
204
282
  }
205
283
 
206
284
  /**
@@ -1,17 +1,17 @@
1
1
  /**
2
- * Compute bounds of a 3-rd degree hermite curve
3
- * Note that this is a 1d case solver
2
+ * Compute `y0,y1` bounds of a cubic hermite spline.
4
3
  * Lower bound will be written into result[offset], upper bounds will be written into result[offset+result_stride]
5
- * Solution is based on https://stackoverflow.com/questions/24809978/calculating-the-bounding-box-of-cubic-bezier-curve
6
- * Differentiation of hermite polynomial is done in WolframAlpha
7
- * 0 = 3 t^2 (m0 + m1 + 2 p0 - 2 p1) - 2 t (2 m0 + m1 + 3 p0 - 3 p1) + m0
8
- * @param {number[]|Float32Array} result
4
+ *
5
+ * @param {number[]|Float32Array} result output will be written here, only y0 and y1
9
6
  * @param {number} result_offset offset into the result array
10
- * @param {number} result_stride
7
+ * @param {number} result_stride useful for mixing multidimensional results
11
8
  * @param {number} p0
12
9
  * @param {number} p1
13
10
  * @param {number} m0
14
11
  * @param {number} m1
12
+ *
13
+ * @author Alex Goldring
14
+ * @copyright Company Named Limited (c) 2025
15
15
  */
16
16
  export function spline_hermite3_bounds(result: number[] | Float32Array, result_offset: number, result_stride: number, p0: number, p1: number, m0: number, m1: number): void;
17
17
  //# sourceMappingURL=spline_hermite3_bounds.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spline_hermite3_bounds.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/spline/spline_hermite3_bounds.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AACH,+CARW,MAAM,EAAE,GAAC,YAAY,iBACrB,MAAM,iBACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QA4EhB"}
1
+ {"version":3,"file":"spline_hermite3_bounds.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/spline/spline_hermite3_bounds.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AACH,+CAXW,MAAM,EAAE,GAAC,YAAY,iBACrB,MAAM,iBACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QAqFhB"}
@@ -4,19 +4,19 @@ import { min2 } from "../min2.js";
4
4
  import { spline_hermite3 } from "./spline_hermite3.js";
5
5
 
6
6
  /**
7
- * Compute bounds of a 3-rd degree hermite curve
8
- * Note that this is a 1d case solver
7
+ * Compute `y0,y1` bounds of a cubic hermite spline.
9
8
  * Lower bound will be written into result[offset], upper bounds will be written into result[offset+result_stride]
10
- * Solution is based on https://stackoverflow.com/questions/24809978/calculating-the-bounding-box-of-cubic-bezier-curve
11
- * Differentiation of hermite polynomial is done in WolframAlpha
12
- * 0 = 3 t^2 (m0 + m1 + 2 p0 - 2 p1) - 2 t (2 m0 + m1 + 3 p0 - 3 p1) + m0
13
- * @param {number[]|Float32Array} result
9
+ *
10
+ * @param {number[]|Float32Array} result output will be written here, only y0 and y1
14
11
  * @param {number} result_offset offset into the result array
15
- * @param {number} result_stride
12
+ * @param {number} result_stride useful for mixing multidimensional results
16
13
  * @param {number} p0
17
14
  * @param {number} p1
18
15
  * @param {number} m0
19
16
  * @param {number} m1
17
+ *
18
+ * @author Alex Goldring
19
+ * @copyright Company Named Limited (c) 2025
20
20
  */
21
21
  export function spline_hermite3_bounds(
22
22
  result,
@@ -24,6 +24,12 @@ export function spline_hermite3_bounds(
24
24
  result_stride,
25
25
  p0, p1, m0, m1) {
26
26
 
27
+ /*
28
+ Solution is based on https://stackoverflow.com/questions/24809978/calculating-the-bounding-box-of-cubic-bezier-curve
29
+ Differentiation of hermite polynomial is done in WolframAlpha:
30
+ 0 = 3 t^2 (m0 + m1 + 2 p0 - 2 p1) - 2 t (2 m0 + m1 + 3 p0 - 3 p1) + m0
31
+ */
32
+
27
33
  assert.greaterThan(result_stride, 0, 'result_stride must be greater than 0');
28
34
  assert.isInteger(result_stride, 'result_stride');
29
35
 
@@ -2,10 +2,10 @@ export default ObservedBoolean;
2
2
  declare class ObservedBoolean extends Boolean {
3
3
  /**
4
4
  *
5
- * @param {boolean} value
5
+ * @param {boolean} [value=false]
6
6
  * @constructor
7
7
  */
8
- constructor(value: boolean);
8
+ constructor(value?: boolean);
9
9
  /**
10
10
  * @readonly
11
11
  * @type {Signal<boolean,boolean>}
@@ -50,7 +50,7 @@ declare class ObservedBoolean extends Boolean {
50
50
  process(f: (arg0: boolean, arg1: boolean) => any, thisArg?: any): this;
51
51
  /**
52
52
  *
53
- * @returns {Boolean}
53
+ * @returns {boolean}
54
54
  */
55
55
  getValue(): boolean;
56
56
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ObservedBoolean.d.ts","sourceRoot":"","sources":["../../../../src/core/model/ObservedBoolean.js"],"names":[],"mappings":";AAGA;IAQI;;;;OAIG;IACH,mBAHW,OAAO,EAcjB;IAtBD;;;OAGG;IACH,oBAFU,MAAM,CAAC,OAAO,EAAC,OAAO,CAAC,CAER;IAYrB;;;;OAIG;IACH,gBAAoB;IAmBxB;;;;OAIG;IACH,WAHW,OAAO,GACL,eAAe,CAa3B;IAED,gBAEC;IAED,iBAEC;IAED;;;OAGG;IACH,YAFW,eAAe,QAIzB;IAED;;;;OAIG;IACH,cAHW,eAAe,GACb,OAAO,CAInB;IAED;;;OAGG;IACH,YAFY,MAAM,CAIjB;IAED;;;;;OAKG;IACH,WAJW,CAAS,IAAO,EAAP,OAAO,EAAC,IAAO,EAAP,OAAO,QAAC,YACzB,GAAC,GACC,IAAI,CAWhB;IAED;;;OAGG;IACH,oBAEC;IAED;;OAEG;IACH,eAEC;IAED,kBAEC;IAED,yBAEC;IAED;;;OAGG;IACH,uBAFW,YAAY,QAItB;IAED;;;OAGG;IACH,yBAFW,YAAY,QAKtB;IAeL;;;OAGG;IACH,4BAFU,OAAO,CAE0B;CAlB1C;;eAIS,eAAe;cAMf,eAAe;;mBAjKN,4BAA4B"}
1
+ {"version":3,"file":"ObservedBoolean.d.ts","sourceRoot":"","sources":["../../../../src/core/model/ObservedBoolean.js"],"names":[],"mappings":";AAGA;IAQI;;;;OAIG;IACH,oBAHW,OAAO,EAcjB;IAtBD;;;OAGG;IACH,oBAFU,MAAM,CAAC,OAAO,EAAC,OAAO,CAAC,CAER;IAYrB;;;;OAIG;IACH,gBAAoB;IAmBxB;;;;OAIG;IACH,WAHW,OAAO,GACL,eAAe,CAa3B;IAED,gBAEC;IAED,iBAEC;IAED;;;OAGG;IACH,YAFW,eAAe,QAIzB;IAED;;;;OAIG;IACH,cAHW,eAAe,GACb,OAAO,CAInB;IAED;;;OAGG;IACH,YAFY,MAAM,CAIjB;IAED;;;;;OAKG;IACH,WAJW,CAAS,IAAO,EAAP,OAAO,EAAC,IAAO,EAAP,OAAO,QAAC,YACzB,GAAC,GACC,IAAI,CAWhB;IAED;;;OAGG;IACH,YAFa,OAAO,CAInB;IAED;;OAEG;IACH,eAEC;IAED,kBAEC;IAED,yBAEC;IAED;;;OAGG;IACH,uBAFW,YAAY,QAItB;IAED;;;OAGG;IACH,yBAFW,YAAY,QAKtB;IAeL;;;OAGG;IACH,4BAFU,OAAO,CAE0B;CAlB1C;;eAIS,eAAe;cAMf,eAAe;;mBAjKN,4BAA4B"}
@@ -11,10 +11,10 @@ class ObservedBoolean extends Boolean {
11
11
 
12
12
  /**
13
13
  *
14
- * @param {boolean} value
14
+ * @param {boolean} [value=false]
15
15
  * @constructor
16
16
  */
17
- constructor(value) {
17
+ constructor(value=false) {
18
18
  super();
19
19
 
20
20
  assert.isBoolean(value, 'value');
@@ -113,7 +113,7 @@ class ObservedBoolean extends Boolean {
113
113
 
114
114
  /**
115
115
  *
116
- * @returns {Boolean}
116
+ * @returns {boolean}
117
117
  */
118
118
  getValue() {
119
119
  return this.__value;
@@ -1 +1 @@
1
- {"version":3,"file":"ObservedEnum.d.ts","sourceRoot":"","sources":["../../../../src/core/model/ObservedEnum.js"],"names":[],"mappings":";AAGA;IACI;;;;;OAKG;IACH,mBAJW,CAAC;;OAiBX;IATG;;;;OAIG;IACH,gBAAoB;IACpB;;MAA0B;IAE1B,0DAA6B;IAGjC;;;OAGG;IACH;;MAEC;IAED;;;;OAIG;IACH,WAHW,CAAC,GACC,YAAY,CAYxB;IAED;;;;OAIG;IACH,OAJa,CAAC,SACH,YAAY,CAAC,CAAC,CAAC,GACb,OAAO,CAInB;IAED;;;OAGG;IACH,YAFW,YAAY,QAItB;IAED;;;OAGG;IACH,YAFa,CAAC,CAIb;IAED,eAEC;IAED;;;;;OAKG;IACH,mBAJW,CAAS,IAAC,EAAD,CAAC,EAAC,IAAC,EAAD,CAAC,QAAC,YACb,GAAC,GACC,IAAI,CAUhB;IAED,YAEC;IAED,yBAEC;CACJ;mBArGkB,4BAA4B"}
1
+ {"version":3,"file":"ObservedEnum.d.ts","sourceRoot":"","sources":["../../../../src/core/model/ObservedEnum.js"],"names":[],"mappings":";AAGA;;;;;;;;;;;;;;;;;;GAkBG;AACH;IACI;;;;OAIG;IACH,mBAHW,CAAC;;OAyBX;IAlBG;;;;OAIG;IACH,gBAAoB;IACpB;;;;OAIG;IACH,mBAA0B;IAE1B;;;OAGG;IACH,oBAFU,MAAM,CAAC,CAAC,EAAC,CAAC,CAAC,CAEQ;IAGjC;;;OAGG;IACH;;MAEC;IAED;;;;OAIG;IACH,WAHW,CAAC,GACC,YAAY,CAYxB;IAED;;;;OAIG;IACH,mBAHW,YAAY,CAAC,GAAC,CAAC,GACb,OAAO,CAInB;IAED;;;OAGG;IACH,QAFY,MAAM,CAcjB;IAED;;;OAGG;IACH,YAFW,YAAY,QAItB;IAED;;;OAGG;IACH,YAFa,CAAC,CAIb;IAED;;;;;OAKG;IACH,mBAJW,CAAS,IAAC,EAAD,CAAC,EAAC,IAAC,EAAD,CAAC,QAAC,YACb,GAAC,GACC,IAAI,CAUhB;IAED,YAEC;IAED,yBAEC;CACJ;mBA9IkB,4BAA4B"}
@@ -1,16 +1,34 @@
1
1
  import { assert } from "../assert.js";
2
2
  import Signal from "../events/signal/Signal.js";
3
3
 
4
+ /**
5
+ * Enumerable value abstraction. Think `enum` keyword in TypeScript or any other programming language.
6
+ * Given a set of valid values, holds one of such values.
7
+ * This is an observable value, meaning you can subscribe to be notified of changes via {@link onChanged} signal.
8
+ *
9
+ * @example
10
+ * const v = new ObservedEnum(7, {
11
+ * ONE: 1,
12
+ * SEVEN: 7
13
+ * });
14
+ *
15
+ * v.getValue(); // 7
16
+ *
17
+ * v.set(1);
18
+ *
19
+ * v.getValue(); // 1
20
+ *
21
+ * v.set(2); // will throw error, as 2 is not a valid enum value
22
+ */
4
23
  class ObservedEnum {
5
24
  /**
6
25
  * @template T
7
26
  * @param {T} value
8
27
  * @param {Object.<string,T>} validSet
9
- * @constructor
10
28
  */
11
29
  constructor(value, validSet) {
12
- assert.equal(typeof validSet, "object", `ValidSet must be of type "object", instead was ${typeof validSet}`);
13
- assert.notEqual(Object.values(validSet).indexOf(value), -1, `Value must be one of [${Object.values(validSet).join(", ")}], instead was "${value}"`);
30
+ assert.isObject(validSet, "validSet");
31
+ assert.enum(value, validSet, "value");
14
32
 
15
33
  /**
16
34
  *
@@ -18,13 +36,22 @@ class ObservedEnum {
18
36
  * @private
19
37
  */
20
38
  this.__value = value;
39
+ /**
40
+ *
41
+ * @type {Object<string, T>}
42
+ * @private
43
+ */
21
44
  this.__validSet = validSet;
22
45
 
46
+ /**
47
+ * @readonly
48
+ * @type {Signal<T,T>}
49
+ */
23
50
  this.onChanged = new Signal();
24
51
  }
25
52
 
26
53
  /**
27
- *
54
+ * Do not modify result
28
55
  * @returns {Object<string, T>}
29
56
  */
30
57
  getValidValueSet() {
@@ -37,7 +64,7 @@ class ObservedEnum {
37
64
  * @returns {ObservedEnum}
38
65
  */
39
66
  set(value) {
40
- assert.notEqual(Object.values(this.__validSet).indexOf(value), -1, `Value must be one of [${Object.values(this.__validSet).join(", ")}], instead was "${value}"`);
67
+ assert.enum(value, this.__validSet, "value")
41
68
 
42
69
  const oldValue = this.__value;
43
70
  if (oldValue !== value) {
@@ -49,14 +76,32 @@ class ObservedEnum {
49
76
  }
50
77
 
51
78
  /**
52
- * @template X
53
- * @param {ObservedEnum<X>} other
79
+ * @template T
80
+ * @param {ObservedEnum<T>} other
54
81
  * @returns {boolean}
55
82
  */
56
83
  equals(other) {
57
84
  return this.__value === other.__value;
58
85
  }
59
86
 
87
+ /**
88
+ *
89
+ * @return {number}
90
+ */
91
+ hash() {
92
+ let hash = 0;
93
+
94
+ for (const n of this.__validSet) {
95
+ if(this.__validSet[n] === this.__value) {
96
+ break;
97
+ }
98
+
99
+ hash++;
100
+ }
101
+
102
+ return hash;
103
+ }
104
+
60
105
  /**
61
106
  *
62
107
  * @param {ObservedEnum} other
@@ -73,10 +118,6 @@ class ObservedEnum {
73
118
  return this.__value;
74
119
  }
75
120
 
76
- invert() {
77
- this.set(!this.__value);
78
- }
79
-
80
121
  /**
81
122
  *
82
123
  * @param {function(T,T)} processor
@@ -2,7 +2,7 @@ export default ObservedInteger;
2
2
  declare class ObservedInteger extends Number {
3
3
  /**
4
4
  *
5
- * @param {Number} [value]
5
+ * @param {number} [value=0]
6
6
  * @constructor
7
7
  */
8
8
  constructor(value?: number);
@@ -13,17 +13,17 @@ declare class ObservedInteger extends Number {
13
13
  readonly onChanged: Signal;
14
14
  /**
15
15
  *
16
- * @type {Number}
16
+ * @type {number}
17
17
  * @private
18
18
  */
19
19
  private __value;
20
20
  toString(): string;
21
21
  /**
22
22
  *
23
- * @param {Number} value
24
- * @returns {ObservedInteger}
23
+ * @param {number} value
24
+ * @returns {this}
25
25
  */
26
- set(value: number): ObservedInteger;
26
+ set(value: number): this;
27
27
  /**
28
28
  * Set value without dispatching change notification
29
29
  * @param {number} value
@@ -64,7 +64,7 @@ declare class ObservedInteger extends Number {
64
64
  decrement(): void;
65
65
  /**
66
66
  *
67
- * @returns {Number}
67
+ * @returns {number}
68
68
  */
69
69
  getValue(): number;
70
70
  /**
@@ -80,7 +80,7 @@ declare class ObservedInteger extends Number {
80
80
  equals(other: ObservedInteger): boolean;
81
81
  /**
82
82
  *
83
- * @returns {Number}
83
+ * @returns {number}
84
84
  */
85
85
  hash(): number;
86
86
  toJSON(): number;
@@ -1 +1 @@
1
- {"version":3,"file":"ObservedInteger.d.ts","sourceRoot":"","sources":["../../../../src/core/model/ObservedInteger.js"],"names":[],"mappings":";AAGA;IAOI;;;;OAIG;IACH,4BAcC;IAzBD;;;OAGG;IACH,oBAFU,MAAM,CAES;IAcrB;;;;OAIG;IACH,gBAAoB;IAYxB,mBAEC;IAED;;;;OAIG;IACH,oBAFa,eAAe,CAa3B;IAED;;;OAGG;IACH,iBAFW,MAAM,QAOhB;IAED;;;OAGG;IACH,UAFY,OAAO,CAIlB;IAED;;;OAGG;IACH,gBAFW,eAAe,QAIzB;IAED;;;OAGG;IACH,iBAFW,MAAM,QAIhB;IAED;;;OAGG;IACH,WAFW,eAAe,QAIzB;IAED;;;OAGG;IACH,YAFW,MAAM,QAIhB;IAED;;OAEG;IACH,kBAEC;IAED;;OAEG;IACH,kBAEC;IAED;;;OAGG;IACH,mBAEC;IAED;;;OAGG;IACH,YAFW,eAAe,QAIzB;IAED;;;;OAIG;IACH,cAHW,eAAe,GACb,OAAO,CAInB;IAED;;;OAGG;IACH,eAEC;IAED,iBAEC;IAED,yBAEC;IAED;;;OAGG;IACH,uBAFW,YAAY,QAatB;IAED;;;OAGG;IACH,yBAFW,YAAY,QAYtB;IAIL;;;OAGG;IACH,4BAFU,OAAO,CAE0B;CAP1C;mBAtMkB,4BAA4B"}
1
+ {"version":3,"file":"ObservedInteger.d.ts","sourceRoot":"","sources":["../../../../src/core/model/ObservedInteger.js"],"names":[],"mappings":";AAIA;IAOI;;;;OAIG;IACH,oBAHW,MAAM,EAgBhB;IAxBD;;;OAGG;IACH,oBAFU,MAAM,CAES;IAarB;;;;OAIG;IACH,gBAAoB;IAYxB,mBAEC;IAED;;;;OAIG;IACH,WAHW,MAAM,GACJ,IAAI,CAchB;IAED;;;OAGG;IACH,iBAFW,MAAM,QAOhB;IAED;;;OAGG;IACH,UAFY,OAAO,CAIlB;IAED;;;OAGG;IACH,gBAFW,eAAe,QAIzB;IAED;;;OAGG;IACH,iBAFW,MAAM,QAIhB;IAED;;;OAGG;IACH,WAFW,eAAe,QAIzB;IAED;;;OAGG;IACH,YAFW,MAAM,QAIhB;IAED;;OAEG;IACH,kBAEC;IAED;;OAEG;IACH,kBAEC;IAED;;;OAGG;IACH,YAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,YAFW,eAAe,QAIzB;IAED;;;;OAIG;IACH,cAHW,eAAe,GACb,OAAO,CAInB;IAED;;;OAGG;IACH,QAFa,MAAM,CAIlB;IAED,iBAEC;IAED,yBAEC;IAED;;;OAGG;IACH,uBAFW,YAAY,QAatB;IAED;;;OAGG;IACH,yBAFW,YAAY,QAYtB;IAIL;;;OAGG;IACH,4BAFU,OAAO,CAE0B;CAP1C;mBAtMkB,4BAA4B"}
@@ -1,4 +1,5 @@
1
1
  import { assert } from "../assert.js";
2
+ import { anyOf, isInfinite, isInteger } from "../debug/matchers/matchers.js";
2
3
  import Signal from "../events/signal/Signal.js";
3
4
 
4
5
  class ObservedInteger extends Number {
@@ -10,19 +11,18 @@ class ObservedInteger extends Number {
10
11
 
11
12
  /**
12
13
  *
13
- * @param {Number} [value]
14
+ * @param {number} [value=0]
14
15
  * @constructor
15
16
  */
16
17
  constructor(value = 0) {
17
18
  super();
18
19
 
19
20
  assert.isNumber(value, 'value');
20
- assert.ok(Number.isInteger(value) || !Number.isFinite(value), `Value must be an integer, instead was ${value}`);
21
-
21
+ assert.that(value,'value',anyOf(isInfinite(),isInteger()))
22
22
 
23
23
  /**
24
24
  *
25
- * @type {Number}
25
+ * @type {number}
26
26
  * @private
27
27
  */
28
28
  this.__value = value;
@@ -31,7 +31,7 @@ class ObservedInteger extends Number {
31
31
 
32
32
  /**
33
33
  *
34
- * @returns {Number}
34
+ * @returns {number}
35
35
  */
36
36
  valueOf() {
37
37
  return this.getValue();
@@ -43,12 +43,13 @@ class ObservedInteger extends Number {
43
43
 
44
44
  /**
45
45
  *
46
- * @param {Number} value
47
- * @returns {ObservedInteger}
46
+ * @param {number} value
47
+ * @returns {this}
48
48
  */
49
49
  set(value) {
50
50
  assert.isNumber(value, 'value');
51
- assert.ok(Number.isInteger(value) || !Number.isFinite(value), `Value must be an integer, instead was ${value}`);
51
+ assert.that(value,'value',anyOf(isInfinite(),isInteger()))
52
+
52
53
 
53
54
  const oldValue = this.__value;
54
55
  if (oldValue !== value) {
@@ -65,7 +66,7 @@ class ObservedInteger extends Number {
65
66
  */
66
67
  setSilent(value) {
67
68
  assert.isNumber(value, 'value');
68
- assert.ok(Number.isInteger(value) || !Number.isFinite(value), `Value must be an integer, instead was ${value}`);
69
+ assert.that(value,'value',anyOf(isInfinite(),isInteger()))
69
70
 
70
71
  this.__value = value;
71
72
  }
@@ -126,7 +127,7 @@ class ObservedInteger extends Number {
126
127
 
127
128
  /**
128
129
  *
129
- * @returns {Number}
130
+ * @returns {number}
130
131
  */
131
132
  getValue() {
132
133
  return this.__value;
@@ -151,7 +152,7 @@ class ObservedInteger extends Number {
151
152
 
152
153
  /**
153
154
  *
154
- * @returns {Number}
155
+ * @returns {number}
155
156
  */
156
157
  hash() {
157
158
  return this.__value;
@@ -51,7 +51,7 @@ export class AnimationCurve {
51
51
  */
52
52
  add(key: Keyframe): number;
53
53
  /**
54
- *
54
+ * Insert multiple keyframes. Input doesn't need to be sorted.
55
55
  * @param {Keyframe[]} keys
56
56
  */
57
57
  addMany(keys: Keyframe[]): void;
@@ -62,26 +62,32 @@ export class AnimationCurve {
62
62
  */
63
63
  remove(key: Keyframe): boolean;
64
64
  /**
65
- * Remove all keys
65
+ * Remove all keys, making the curve empty.
66
66
  */
67
67
  clear(): void;
68
68
  /**
69
- * Number of keys
69
+ * Does this curve have any frames?
70
+ * @return {boolean} true if keyframe count == 0, false otherwise
71
+ */
72
+ isEmpty(): boolean;
73
+ /**
74
+ * Number of keys, will be 0 if curve is empty
70
75
  * @returns {number}
71
76
  */
72
77
  get length(): number;
73
78
  /**
74
- * Time of the first keyframe, returns 0 if there are no keys
79
+ * Timestamp of the first keyframe, returns 0 if there are no keys
75
80
  * @returns {number}
76
81
  */
77
82
  get start_time(): number;
78
83
  /**
79
- * Time of the last chronological key in the curve
84
+ * Time of the last chronological key in the curve.
85
+ * returns 0 if there are no keys.
80
86
  * @return {number}
81
87
  */
82
88
  get end_time(): number;
83
89
  /**
84
- * Time difference between first and last frame
90
+ * Time difference between first and last frame.
85
91
  * @returns {number}
86
92
  */
87
93
  get duration(): number;
@@ -1 +1 @@
1
- {"version":3,"file":"AnimationCurve.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/AnimationCurve.js"],"names":[],"mappings":"AAqBA;;;;;;;GAOG;AACH;IAkFI;;;;OAIG;IACH,kBAHW,QAAQ,EAAE,GACR,cAAc,CAQ1B;IAgRD;;;;;;;OAOG;IACH,6BANW,MAAM,eACN,MAAM,YACN,MAAM,aACN,MAAM,GACL,cAAc,CAUzB;IAED;;;;;;OAMG;IACH,4BALW,MAAM,YACN,MAAM,UACN,MAAM,GACL,cAAc,CAOzB;IAED;;;;;;;OAOG;IACH,0BANW,MAAM,eACN,MAAM,YACN,MAAM,aACN,MAAM,GACL,cAAc,CAYzB;IA9ZD;;;OAGG;IACH,eAFU,QAAQ,EAAE,CAEV;IAEV;;;;OAIG;IACH,SAHW,QAAQ,GACN,MAAM,CAgClB;IAED;;;OAGG;IACH,cAFW,QAAQ,EAAE,QAUpB;IAED;;;;OAIG;IACH,YAHW,QAAQ,GACN,OAAO,CAYnB;IAED;;OAEG;IACH,cAEC;IAeD;;;OAGG;IACH,cAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,kBAFa,MAAM,CAYlB;IAED;;;OAGG;IACH,gBAFY,MAAM,CAYjB;IAED;;;OAGG;IACH,gBAFa,MAAM,CAelB;IAED;;;;OAIG;IACH,wBAHW,MAAM,GACJ,MAAM,CA0ClB;IAED;;;;OAIG;IACH,eAHW,MAAM,GACL,MAAM,CAoCjB;IAED;;;;OAIG;IACH,qBAFW,MAAM,QAmChB;IAED;;;;OAIG;IACH,sBAHW,MAAM,UACN,MAAM,QAWhB;IAED,0BAKC;IAED;;;;OAIG;IACH,cAHW,cAAc,GACb,OAAO,CAIlB;IAED;;;OAGG;IACH,YAFW,cAAc,QAIxB;IAED;;;OAGG;IACH,SAFY,cAAc,CAQzB;IAED;;;OAGG;IACH,QAFY,MAAM,CAIjB;IAED;;MAIC;IAED;;aAeC;CAqDJ;yBApbwB,eAAe"}
1
+ {"version":3,"file":"AnimationCurve.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/AnimationCurve.js"],"names":[],"mappings":"AAqBA;;;;;;;GAOG;AACH;IA4WI;;;;OAIG;IACH,kBAHW,QAAQ,EAAE,GACR,cAAc,CAQ1B;IAED;;;;;;;OAOG;IACH,6BANW,MAAM,eACN,MAAM,YACN,MAAM,aACN,MAAM,GACL,cAAc,CAUzB;IAED;;;;;;OAMG;IACH,4BALW,MAAM,YACN,MAAM,UACN,MAAM,GACL,cAAc,CAOzB;IAED;;;;;;;OAOG;IACH,0BANW,MAAM,eACN,MAAM,YACN,MAAM,aACN,MAAM,GACL,cAAc,CAYzB;IA1aD;;;OAGG;IACH,eAFU,QAAQ,EAAE,CAEV;IAEV;;;;OAIG;IACH,SAHW,QAAQ,GACN,MAAM,CAiClB;IAED;;;OAGG;IACH,cAFW,QAAQ,EAAE,QAUpB;IAED;;;;OAIG;IACH,YAHW,QAAQ,GACN,OAAO,CAYnB;IAED;;OAEG;IACH,cAEC;IAGD;;;OAGG;IACH,WAFY,OAAO,CAIlB;IAED;;;OAGG;IACH,cAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,kBAFa,MAAM,CAYlB;IAED;;;;OAIG;IACH,gBAFY,MAAM,CAYjB;IAED;;;OAGG;IACH,gBAFa,MAAM,CAgBlB;IAED;;;;OAIG;IACH,wBAHW,MAAM,GACJ,MAAM,CA0ClB;IAED;;;;OAIG;IACH,eAHW,MAAM,GACL,MAAM,CAoCjB;IAED;;;;OAIG;IACH,qBAFW,MAAM,QAmChB;IAED;;;;OAIG;IACH,sBAHW,MAAM,UACN,MAAM,QAWhB;IAED,0BAKC;IAED;;;;OAIG;IACH,cAHW,cAAc,GACb,OAAO,CAIlB;IAED;;;OAGG;IACH,YAFW,cAAc,QAIxB;IAED;;;OAGG;IACH,SAFY,cAAc,CAQzB;IAED;;;OAGG;IACH,QAFY,MAAM,CAIjB;IAED;;MAIC;IAED;;aAeC;CAkEJ;yBAhcwB,eAAe"}
@@ -62,6 +62,7 @@ export class AnimationCurve {
62
62
  } else {
63
63
 
64
64
  // figure out the right place to insert the key
65
+ // TODO make use of this.getKeyIndexByTime instead
65
66
  const i = binarySearchHighIndex(keys, key.time, compareKeyframeToTime, 0, last_key_index);
66
67
 
67
68
  // insert key at the right place
@@ -72,7 +73,7 @@ export class AnimationCurve {
72
73
  }
73
74
 
74
75
  /**
75
- *
76
+ * Insert multiple keyframes. Input doesn't need to be sorted.
76
77
  * @param {Keyframe[]} keys
77
78
  */
78
79
  addMany(keys) {
@@ -103,27 +104,23 @@ export class AnimationCurve {
103
104
  }
104
105
 
105
106
  /**
106
- * Remove all keys
107
+ * Remove all keys, making the curve empty.
107
108
  */
108
109
  clear() {
109
110
  this.keys.splice(0, this.keys.length);
110
111
  }
111
112
 
113
+
112
114
  /**
113
- *
114
- * @param {Keyframe[]} keys
115
- * @returns {AnimationCurve}
115
+ * Does this curve have any frames?
116
+ * @return {boolean} true if keyframe count == 0, false otherwise
116
117
  */
117
- static from(keys) {
118
- const curve = new AnimationCurve();
119
-
120
- curve.addMany(keys);
121
-
122
- return curve;
118
+ isEmpty() {
119
+ return this.keys.length === 0;
123
120
  }
124
121
 
125
122
  /**
126
- * Number of keys
123
+ * Number of keys, will be 0 if curve is empty
127
124
  * @returns {number}
128
125
  */
129
126
  get length() {
@@ -131,7 +128,7 @@ export class AnimationCurve {
131
128
  }
132
129
 
133
130
  /**
134
- * Time of the first keyframe, returns 0 if there are no keys
131
+ * Timestamp of the first keyframe, returns 0 if there are no keys
135
132
  * @returns {number}
136
133
  */
137
134
  get start_time() {
@@ -147,7 +144,8 @@ export class AnimationCurve {
147
144
  }
148
145
 
149
146
  /**
150
- * Time of the last chronological key in the curve
147
+ * Time of the last chronological key in the curve.
148
+ * returns 0 if there are no keys.
151
149
  * @return {number}
152
150
  */
153
151
  get end_time() {
@@ -163,7 +161,7 @@ export class AnimationCurve {
163
161
  }
164
162
 
165
163
  /**
166
- * Time difference between first and last frame
164
+ * Time difference between first and last frame.
167
165
  * @returns {number}
168
166
  */
169
167
  get duration() {
@@ -172,6 +170,7 @@ export class AnimationCurve {
172
170
  const key_count = keys.length;
173
171
 
174
172
  if (key_count < 2) {
173
+ // too few frames to compare
175
174
  return 0;
176
175
  }
177
176
 
@@ -392,6 +391,19 @@ export class AnimationCurve {
392
391
 
393
392
  }
394
393
 
394
+ /**
395
+ *
396
+ * @param {Keyframe[]} keys
397
+ * @returns {AnimationCurve}
398
+ */
399
+ static from(keys) {
400
+ const curve = new AnimationCurve();
401
+
402
+ curve.addMany(keys);
403
+
404
+ return curve;
405
+ }
406
+
395
407
  /**
396
408
  *
397
409
  * @param {number} [timeStart]
@@ -2,7 +2,7 @@ import { max2 } from "../../../core/math/max2.js";
2
2
  import { min2 } from "../../../core/math/min2.js";
3
3
  import { spline_hermite3_bounds } from "../../../core/math/spline/spline_hermite3_bounds.js";
4
4
 
5
- const temp_bounds = new Float32Array(4);
5
+ const temp_bounds = new Float32Array(2);
6
6
 
7
7
  /**
8
8
  * Compute bounding box for a given curve. X-axis is time, Y-axis is value.
@@ -3,9 +3,10 @@
3
3
  * Intended to reduce complexity of a curve to improve performance and lower memory usage
4
4
  * @param {AnimationCurve} curve
5
5
  * @param {number} [error_tolerance] how much of a loss to accept, this is relative to normalized value bounds of the curve
6
+ * @returns {number} number of removed keys, 0 if curve was unchanged
6
7
  *
7
8
  * @author Alex Goldring
8
9
  * @copyright Company Named Limited (c) 2025
9
10
  */
10
- export function animation_curve_optimize(curve: AnimationCurve, error_tolerance?: number): void;
11
+ export function animation_curve_optimize(curve: AnimationCurve, error_tolerance?: number): number;
11
12
  //# sourceMappingURL=animation_curve_optimize.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"animation_curve_optimize.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/animation_curve_optimize.js"],"names":[],"mappings":"AAkDA;;;;;;;;GAQG;AACH,gDANW,cAAc,oBACd,MAAM,QA6ChB"}
1
+ {"version":3,"file":"animation_curve_optimize.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/curve/animation_curve_optimize.js"],"names":[],"mappings":"AAkDA;;;;;;;;;GASG;AACH,gDAPW,cAAc,oBACd,MAAM,GACJ,MAAM,CAkDlB"}
@@ -53,6 +53,7 @@ function compute_keyframe_value_effect(
53
53
  * Intended to reduce complexity of a curve to improve performance and lower memory usage
54
54
  * @param {AnimationCurve} curve
55
55
  * @param {number} [error_tolerance] how much of a loss to accept, this is relative to normalized value bounds of the curve
56
+ * @returns {number} number of removed keys, 0 if curve was unchanged
56
57
  *
57
58
  * @author Alex Goldring
58
59
  * @copyright Company Named Limited (c) 2025
@@ -68,6 +69,8 @@ export function animation_curve_optimize(curve, error_tolerance = 1e-3) {
68
69
 
69
70
  const keyframes = curve.keys;
70
71
 
72
+ const initial_key_count = key_count;
73
+
71
74
  for (let i = 1; i < key_count; i++) {
72
75
  const key_previous = keyframes[i - 1];
73
76
  const key_current = keyframes[i];
@@ -97,4 +100,7 @@ export function animation_curve_optimize(curve, error_tolerance = 1e-3) {
97
100
  key_count--;
98
101
  }
99
102
  }
103
+
104
+ // number of removed keys
105
+ return initial_key_count - key_count;
100
106
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EntityComponentDataset.d.ts","sourceRoot":"","sources":["../../../../src/engine/ecs/EntityComponentDataset.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EntityComponentDataset.d.ts","sourceRoot":"","sources":["../../../../src/engine/ecs/EntityComponentDataset.js"],"names":[],"mappings":"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"}
@@ -1028,9 +1028,9 @@ export class EntityComponentDataset {
1028
1028
  }
1029
1029
 
1030
1030
  /**
1031
- *
1031
+ * Internally every component class is mapped to an index, this method is used to retrieve such mapping.
1032
1032
  * @param {Function|Class} klass
1033
- * @returns {number}
1033
+ * @returns {number} integer index, -1 if not found
1034
1034
  */
1035
1035
  computeComponentTypeIndex(klass) {
1036
1036
  assert.defined(klass, "klass");
@@ -1061,6 +1061,9 @@ export class EntityComponentDataset {
1061
1061
  }
1062
1062
 
1063
1063
  /**
1064
+ * Retrieves any instance of a given component.
1065
+ * If no component instances exist - component will be `null` and entity will be `-1`.
1066
+ * Useful for singleton components such as a camera or an audio listener.
1064
1067
  * @template T
1065
1068
  * @param {Class<T>} component_type
1066
1069
  * @returns {{entity:number, component:T}}
@@ -1069,12 +1072,22 @@ export class EntityComponentDataset {
1069
1072
  let entity = -1;
1070
1073
  let component = null;
1071
1074
 
1072
- this.traverseComponents(component_type, (c, i) => {
1073
- entity = i;
1074
- component = c;
1075
+ const index = this.computeComponentTypeIndex(component_type);
1075
1076
 
1076
- return false;
1077
- });
1077
+ if(index!== -1) {
1078
+
1079
+ const components = this.components[index];
1080
+ for (const entity_key in components) {
1081
+ const c = components[entity_key];
1082
+
1083
+ if(c !== undefined){
1084
+ entity = Number(entity_key);
1085
+ component = c;
1086
+ break;
1087
+ }
1088
+
1089
+ }
1090
+ }
1078
1091
 
1079
1092
  return {
1080
1093
  entity,