@thi.ng/timestep 0.1.0 → 0.2.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.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2023-04-19T09:28:07Z
3
+ - **Last updated**: 2023-04-28T17:22:36Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -9,6 +9,19 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
9
9
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
10
10
  and/or version bumps of transitive dependencies.
11
11
 
12
+ ## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/timestep@0.2.0) (2023-04-28)
13
+
14
+ #### 🚀 Features
15
+
16
+ - add INotify support, add fixed time field ([b68c0c6](https://github.com/thi-ng/umbrella/commit/b68c0c6))
17
+ - add integrateAll/interpolateAll() helpers ([71087cf](https://github.com/thi-ng/umbrella/commit/71087cf))
18
+
19
+ ### [0.1.1](https://github.com/thi-ng/umbrella/tree/@thi.ng/timestep@0.1.1) (2023-04-25)
20
+
21
+ #### ♻️ Refactoring
22
+
23
+ - update AState, expose prev & curr ([8d5356b](https://github.com/thi-ng/umbrella/commit/8d5356b))
24
+
12
25
  ## [0.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/timestep@0.1.0) (2023-04-19)
13
26
 
14
27
  #### 🚀 Features
package/api.d.ts CHANGED
@@ -36,6 +36,10 @@ export interface IUpdatable {
36
36
  interpolate(alpha: number, ctx: ReadonlyTimeStep): void;
37
37
  }
38
38
  export interface ReadonlyTimeStep {
39
+ /**
40
+ * Simulation time since start (resolution {@link ReadonlyTimeStep.dt}).
41
+ */
42
+ readonly t: number;
39
43
  /**
40
44
  * Configured timestep (in seconds)
41
45
  */
@@ -88,4 +92,14 @@ export interface TimeStepOpts {
88
92
  }
89
93
  export type StateUpdate<T> = (curr: T, dt: number, ctx: ReadonlyTimeStep) => T;
90
94
  export type StateInterpolation<T> = (prev: T, curr: T, alpha: number, ctx: ReadonlyTimeStep) => T;
95
+ /**
96
+ * Event ID for {@link TimeStep.addListener} to be notified of individual
97
+ * {@link IUpdatable.integrate} iterations.
98
+ */
99
+ export declare const EVENT_INTEGRATE = "integrate";
100
+ /**
101
+ * Event ID for {@link TimeStep.addListener} to be notified of calls to
102
+ * {@link TimeStep.update} (triggered at the very end of a frame update).
103
+ */
104
+ export declare const EVENT_FRAME = "frame";
91
105
  //# sourceMappingURL=api.d.ts.map
package/api.js CHANGED
@@ -1 +1,10 @@
1
- export {};
1
+ /**
2
+ * Event ID for {@link TimeStep.addListener} to be notified of individual
3
+ * {@link IUpdatable.integrate} iterations.
4
+ */
5
+ export const EVENT_INTEGRATE = "integrate";
6
+ /**
7
+ * Event ID for {@link TimeStep.addListener} to be notified of calls to
8
+ * {@link TimeStep.update} (triggered at the very end of a frame update).
9
+ */
10
+ export const EVENT_FRAME = "frame";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/timestep",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Deterministic fixed timestep simulation updates with state interpolation",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -35,8 +35,8 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@thi.ng/api": "^8.8.0",
38
- "@thi.ng/math": "^5.4.8",
39
- "@thi.ng/vectors": "^7.6.12"
38
+ "@thi.ng/math": "^5.4.9",
39
+ "@thi.ng/vectors": "^7.6.13"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@microsoft/api-extractor": "^7.34.4",
@@ -88,5 +88,5 @@
88
88
  "status": "alpha",
89
89
  "year": 2023
90
90
  },
91
- "gitHead": "3a56bc490f1e68754762a503d06327b5b34ff7eb\n"
91
+ "gitHead": "e71e2d061ac0a754ce4899bb59208afb8b3d94b2\n"
92
92
  }
package/state.d.ts CHANGED
@@ -11,8 +11,8 @@ export declare abstract class AState<T> implements IDeref<T>, IUpdatable {
11
11
  value: T;
12
12
  update: StateUpdate<T>;
13
13
  mix: StateInterpolation<T>;
14
- protected prev: T;
15
- protected curr: T;
14
+ curr: T;
15
+ prev: T;
16
16
  constructor(value: T, update: StateUpdate<T>, mix: StateInterpolation<T>);
17
17
  deref(): T;
18
18
  integrate(dt: number, ctx: ReadonlyTimeStep): void;
package/timestep.d.ts CHANGED
@@ -1,14 +1,21 @@
1
- import type { IUpdatable, TimeStepOpts } from "./api.js";
2
- export declare class TimeStep {
3
- current: number;
1
+ import { type Event, type INotify, type Listener } from "@thi.ng/api";
2
+ import { type IUpdatable, type ReadonlyTimeStep, type TimeStepOpts } from "./api.js";
3
+ export declare class TimeStep implements INotify {
4
4
  start: number;
5
5
  dt: number;
6
6
  maxFrameTime: number;
7
7
  scale: number;
8
+ t: number;
9
+ current: number;
8
10
  accumulator: number;
9
11
  frame: number;
10
12
  updates: number;
13
+ protected __eventIntegrate: Event;
14
+ protected __eventFrame: Event;
11
15
  constructor(opts?: Partial<TimeStepOpts>);
16
+ addListener(id: string, fn: Listener, scope?: any): boolean;
17
+ removeListener(id: string, fn: Listener, scope?: any): boolean;
18
+ notify(event: Event): boolean;
12
19
  /**
13
20
  * Updates internal time to given new time `now` (in seconds) and performs
14
21
  * the required number of fixed timesteps to integrate and interpolate the
@@ -27,4 +34,20 @@ export declare class TimeStep {
27
34
  update(now: number, items: IUpdatable[], interpolate?: boolean): void;
28
35
  }
29
36
  export declare const defTimeStep: (opts?: Partial<TimeStepOpts>) => TimeStep;
37
+ /**
38
+ * Calls {@link IUpdatable.integrate} for all given items (in given order).
39
+ *
40
+ * @param dt
41
+ * @param ctx
42
+ * @param items
43
+ */
44
+ export declare const integrateAll: (dt: number, ctx: ReadonlyTimeStep, ...items: IUpdatable[]) => void;
45
+ /**
46
+ * Calls {@link IUpdatable.interpolate} for all given items (in given order).
47
+ *
48
+ * @param dt
49
+ * @param ctx
50
+ * @param items
51
+ */
52
+ export declare const interpolateAll: (alpha: number, ctx: ReadonlyTimeStep, ...items: IUpdatable[]) => void;
30
53
  //# sourceMappingURL=timestep.d.ts.map
package/timestep.js CHANGED
@@ -1,5 +1,9 @@
1
- export class TimeStep {
1
+ import { __decorate } from "tslib";
2
+ import { INotifyMixin, } from "@thi.ng/api";
3
+ import { EVENT_FRAME, EVENT_INTEGRATE, } from "./api.js";
4
+ let TimeStep = class TimeStep {
2
5
  constructor(opts) {
6
+ this.t = 0;
3
7
  this.current = 0;
4
8
  this.accumulator = 0;
5
9
  this.frame = 0;
@@ -15,7 +19,18 @@ export class TimeStep {
15
19
  this.maxFrameTime = $opts.maxFrameTime;
16
20
  this.scale = $opts.scale;
17
21
  this.start = $opts.startTime * this.scale;
22
+ this.__eventIntegrate = Object.freeze({
23
+ id: EVENT_INTEGRATE,
24
+ target: this,
25
+ });
26
+ this.__eventFrame = Object.freeze({ id: EVENT_FRAME, target: this });
18
27
  }
28
+ // @ts-ignore mixin
29
+ addListener(id, fn, scope) { }
30
+ // @ts-ignore mixin
31
+ removeListener(id, fn, scope) { }
32
+ // @ts-ignore mixin
33
+ notify(event) { }
19
34
  /**
20
35
  * Updates internal time to given new time `now` (in seconds) and performs
21
36
  * the required number of fixed timesteps to integrate and interpolate the
@@ -33,8 +48,6 @@ export class TimeStep {
33
48
  */
34
49
  update(now, items, interpolate = true) {
35
50
  now = now * this.scale - this.start;
36
- if (this.current < 0)
37
- this.current = now;
38
51
  this.accumulator += Math.min(now - this.current, this.maxFrameTime);
39
52
  this.current = now;
40
53
  const n = items.length;
@@ -42,8 +55,10 @@ export class TimeStep {
42
55
  while (this.accumulator >= dt) {
43
56
  for (let i = 0; i < n; i++)
44
57
  items[i].integrate(dt, this);
58
+ this.t += dt;
45
59
  this.accumulator -= dt;
46
60
  this.updates++;
61
+ this.notify(this.__eventIntegrate);
47
62
  }
48
63
  if (interpolate) {
49
64
  const alpha = this.accumulator / dt;
@@ -51,6 +66,33 @@ export class TimeStep {
51
66
  items[i].interpolate(alpha, this);
52
67
  }
53
68
  this.frame++;
69
+ this.notify(this.__eventFrame);
54
70
  }
55
- }
71
+ };
72
+ TimeStep = __decorate([
73
+ INotifyMixin
74
+ ], TimeStep);
75
+ export { TimeStep };
56
76
  export const defTimeStep = (opts) => new TimeStep(opts);
77
+ /**
78
+ * Calls {@link IUpdatable.integrate} for all given items (in given order).
79
+ *
80
+ * @param dt
81
+ * @param ctx
82
+ * @param items
83
+ */
84
+ export const integrateAll = (dt, ctx, ...items) => {
85
+ for (let i = 0, n = items.length; i < n; i++)
86
+ items[i].integrate(dt, ctx);
87
+ };
88
+ /**
89
+ * Calls {@link IUpdatable.interpolate} for all given items (in given order).
90
+ *
91
+ * @param dt
92
+ * @param ctx
93
+ * @param items
94
+ */
95
+ export const interpolateAll = (alpha, ctx, ...items) => {
96
+ for (let i = 0, n = items.length; i < n; i++)
97
+ items[i].interpolate(alpha, ctx);
98
+ };