@flighthq/clock 0.2.1-next.459.fb59cc5 → 0.2.1-next.585.c7219b8
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/dist/clock.d.ts +15 -0
- package/dist/clock.d.ts.map +1 -0
- package/dist/clock.js +122 -0
- package/dist/clock.js.map +1 -0
- package/dist/{enableClockSignals.d.ts → clockSignals.d.ts} +1 -1
- package/dist/clockSignals.d.ts.map +1 -0
- package/dist/{enableClockSignals.js → clockSignals.js} +1 -1
- package/dist/clockSignals.js.map +1 -0
- package/dist/index.d.ts +2 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -11
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/clock.test.ts +298 -0
- package/src/{enableClockSignals.test.ts → clockSignals.test.ts} +2 -2
- package/dist/addClockChild.d.ts +0 -4
- package/dist/addClockChild.d.ts.map +0 -1
- package/dist/addClockChild.js +0 -20
- package/dist/addClockChild.js.map +0 -1
- package/dist/advanceClock.d.ts +0 -3
- package/dist/advanceClock.d.ts.map +0 -1
- package/dist/advanceClock.js +0 -19
- package/dist/advanceClock.js.map +0 -1
- package/dist/createClock.d.ts +0 -4
- package/dist/createClock.d.ts.map +0 -1
- package/dist/createClock.js +0 -22
- package/dist/createClock.js.map +0 -1
- package/dist/disposeClock.d.ts +0 -3
- package/dist/disposeClock.d.ts.map +0 -1
- package/dist/disposeClock.js +0 -18
- package/dist/disposeClock.js.map +0 -1
- package/dist/enableClockSignals.d.ts.map +0 -1
- package/dist/enableClockSignals.js.map +0 -1
- package/dist/getClockEffectiveScale.d.ts +0 -3
- package/dist/getClockEffectiveScale.d.ts.map +0 -1
- package/dist/getClockEffectiveScale.js +0 -13
- package/dist/getClockEffectiveScale.js.map +0 -1
- package/dist/getClockParent.d.ts +0 -3
- package/dist/getClockParent.d.ts.map +0 -1
- package/dist/getClockParent.js +0 -6
- package/dist/getClockParent.js.map +0 -1
- package/dist/isClockEffectivelyPaused.d.ts +0 -3
- package/dist/isClockEffectivelyPaused.d.ts.map +0 -1
- package/dist/isClockEffectivelyPaused.js +0 -12
- package/dist/isClockEffectivelyPaused.js.map +0 -1
- package/dist/pauseClock.d.ts +0 -4
- package/dist/pauseClock.d.ts.map +0 -1
- package/dist/pauseClock.js +0 -11
- package/dist/pauseClock.js.map +0 -1
- package/dist/resetClock.d.ts +0 -3
- package/dist/resetClock.d.ts.map +0 -1
- package/dist/resetClock.js +0 -7
- package/dist/resetClock.js.map +0 -1
- package/dist/setClockScale.d.ts +0 -3
- package/dist/setClockScale.d.ts.map +0 -1
- package/dist/setClockScale.js +0 -6
- package/dist/setClockScale.js.map +0 -1
- package/src/addClockChild.test.ts +0 -49
- package/src/advanceClock.test.ts +0 -91
- package/src/createClock.test.ts +0 -36
- package/src/disposeClock.test.ts +0 -40
- package/src/getClockEffectiveScale.test.ts +0 -15
- package/src/getClockParent.test.ts +0 -14
- package/src/isClockEffectivelyPaused.test.ts +0 -19
- package/src/pauseClock.test.ts +0 -18
- package/src/resetClock.test.ts +0 -15
- package/src/setClockScale.test.ts +0 -10
package/dist/clock.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Clock, ClockOptions } from '@flighthq/types';
|
|
2
|
+
export declare function addClockChild(parent: Clock, child: Clock): void;
|
|
3
|
+
export declare function advanceClock(clock: Clock, deltaSeconds: number): void;
|
|
4
|
+
export declare function createChildClock(parent: Clock, options?: Readonly<ClockOptions>): Clock;
|
|
5
|
+
export declare function createClock(options?: Readonly<ClockOptions>): Clock;
|
|
6
|
+
export declare function disposeClock(clock: Clock): void;
|
|
7
|
+
export declare function getClockEffectiveScale(clock: Readonly<Clock>): number;
|
|
8
|
+
export declare function getClockParent(clock: Readonly<Clock>): Clock | null;
|
|
9
|
+
export declare function isClockEffectivelyPaused(clock: Readonly<Clock>): boolean;
|
|
10
|
+
export declare function pauseClock(clock: Clock): void;
|
|
11
|
+
export declare function removeClockChild(parent: Clock, child: Clock): void;
|
|
12
|
+
export declare function resetClock(clock: Clock): void;
|
|
13
|
+
export declare function resumeClock(clock: Clock): void;
|
|
14
|
+
export declare function setClockScale(clock: Clock, scale: number): void;
|
|
15
|
+
//# sourceMappingURL=clock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAI3D,wBAAgB,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAK/D;AAQD,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CASrE;AAID,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,KAAK,CAIvF;AAID,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,KAAK,CAUnE;AAMD,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAQ/C;AAKD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,MAAM,CAQrE;AAID,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,CAEnE;AAID,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,OAAO,CAOxE;AAID,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAE7C;AAID,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAKlE;AAID,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAG7C;AAID,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAE9C;AAID,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE/D"}
|
package/dist/clock.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { clearSignal, emitSignal } from '@flighthq/signals';
|
|
2
|
+
// Attaches `child` under `parent`, detaching it from any previous parent first (reparent-safe). After
|
|
3
|
+
// this, advancing `parent` cascades into `child`. A no-op if `child` is already parented here.
|
|
4
|
+
export function addClockChild(parent, child) {
|
|
5
|
+
if (child.parent === parent)
|
|
6
|
+
return;
|
|
7
|
+
if (child.parent !== null)
|
|
8
|
+
removeClockChild(child.parent, child);
|
|
9
|
+
child.parent = parent;
|
|
10
|
+
parent.children.push(child);
|
|
11
|
+
}
|
|
12
|
+
// Advances a clock tree by one step. `deltaSeconds` is the real elapsed seconds for a root clock (the
|
|
13
|
+
// value the frame loop supplies); the cascade feeds each child its parent's already-scaled delta. Each
|
|
14
|
+
// clock's scaled delta is `paused ? 0 : deltaSeconds * scale`; that becomes its deltaTime, accumulates
|
|
15
|
+
// into elapsed, emits its (opt-in) onTick, and drives its children — so scale and pause compose down the
|
|
16
|
+
// whole subtree in one pass. Pre-order: a clock's onTick fires before its children advance. Call once per
|
|
17
|
+
// frame on the root: advanceClock(root, dtSeconds).
|
|
18
|
+
export function advanceClock(clock, deltaSeconds) {
|
|
19
|
+
const scaledDelta = clock.paused ? 0 : deltaSeconds * clock.scale;
|
|
20
|
+
clock.deltaTime = scaledDelta;
|
|
21
|
+
clock.elapsed += scaledDelta;
|
|
22
|
+
if (clock.onTick !== null)
|
|
23
|
+
emitSignal(clock.onTick, scaledDelta);
|
|
24
|
+
const children = clock.children;
|
|
25
|
+
for (let i = 0; i < children.length; i++) {
|
|
26
|
+
advanceClock(children[i], scaledDelta);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Allocates a child clock and attaches it to `parent` in one step. Equivalent to createClock followed by
|
|
30
|
+
// addClockChild; the child inherits `parent`'s scale and pause state through the advanceClock cascade.
|
|
31
|
+
export function createChildClock(parent, options) {
|
|
32
|
+
const child = createClock(options);
|
|
33
|
+
addClockChild(parent, child);
|
|
34
|
+
return child;
|
|
35
|
+
}
|
|
36
|
+
// Allocates a root clock (no parent). Defaults to realtime and running; pass options to start scaled or
|
|
37
|
+
// paused. Drive it each frame with advanceClock(clock, dtSeconds).
|
|
38
|
+
export function createClock(options) {
|
|
39
|
+
return {
|
|
40
|
+
scale: options?.scale ?? 1,
|
|
41
|
+
paused: options?.paused ?? false,
|
|
42
|
+
deltaTime: 0,
|
|
43
|
+
elapsed: 0,
|
|
44
|
+
parent: null,
|
|
45
|
+
children: [],
|
|
46
|
+
onTick: null,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Detaches a clock from its parent, releases its children, and drops any onTick listeners so nothing
|
|
50
|
+
// keeps the subtree — or the clock's subscribers — reachable through it: the parent no longer references
|
|
51
|
+
// this clock, each child becomes a root, and the onTick slot list is cleared. The clock is then plain
|
|
52
|
+
// GC-managed memory (there is no GPU or native resource to free — that would be destroy*).
|
|
53
|
+
export function disposeClock(clock) {
|
|
54
|
+
if (clock.parent !== null)
|
|
55
|
+
removeClockChild(clock.parent, clock);
|
|
56
|
+
const children = clock.children;
|
|
57
|
+
for (let i = 0; i < children.length; i++) {
|
|
58
|
+
children[i].parent = null;
|
|
59
|
+
}
|
|
60
|
+
children.length = 0;
|
|
61
|
+
if (clock.onTick !== null)
|
|
62
|
+
clearSignal(clock.onTick);
|
|
63
|
+
}
|
|
64
|
+
// The clock's realtime rate accounting for the hierarchy: the product of its own scale and every
|
|
65
|
+
// ancestor's scale. A root clock's effective scale is just its own. This is what `deltaTime` divided by
|
|
66
|
+
// the loop's real delta would equal (when nothing in the chain is paused).
|
|
67
|
+
export function getClockEffectiveScale(clock) {
|
|
68
|
+
let scale = clock.scale;
|
|
69
|
+
let current = clock.parent;
|
|
70
|
+
while (current !== null) {
|
|
71
|
+
scale *= current.scale;
|
|
72
|
+
current = current.parent;
|
|
73
|
+
}
|
|
74
|
+
return scale;
|
|
75
|
+
}
|
|
76
|
+
// The clock's parent, or null if it is a root. Convenience accessor for the `parent` field; hierarchy is
|
|
77
|
+
// changed through addClockChild / removeClockChild, not by assigning this.
|
|
78
|
+
export function getClockParent(clock) {
|
|
79
|
+
return clock.parent;
|
|
80
|
+
}
|
|
81
|
+
// Whether this clock receives a zero delta on the next advance: true if the clock itself or any ancestor
|
|
82
|
+
// is paused. A clock can be locally running yet effectively paused because a parent is paused.
|
|
83
|
+
export function isClockEffectivelyPaused(clock) {
|
|
84
|
+
let current = clock;
|
|
85
|
+
while (current !== null) {
|
|
86
|
+
if (current.paused)
|
|
87
|
+
return true;
|
|
88
|
+
current = current.parent;
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
// Pauses the clock: it and its whole subtree receive a zero delta on subsequent advances, so elapsed
|
|
93
|
+
// freezes until resumed. Local state — a child paused this way stays paused even if its parent resumes.
|
|
94
|
+
export function pauseClock(clock) {
|
|
95
|
+
clock.paused = true;
|
|
96
|
+
}
|
|
97
|
+
// Detaches `child` from `parent`, making it a root clock again. A no-op if `child` is not a child of
|
|
98
|
+
// `parent`.
|
|
99
|
+
export function removeClockChild(parent, child) {
|
|
100
|
+
const index = parent.children.indexOf(child);
|
|
101
|
+
if (index === -1)
|
|
102
|
+
return;
|
|
103
|
+
parent.children.splice(index, 1);
|
|
104
|
+
child.parent = null;
|
|
105
|
+
}
|
|
106
|
+
// Clears the clock's accumulated time back to the start: elapsed and deltaTime become 0. Does not touch
|
|
107
|
+
// scale, pause, or the hierarchy, and does not reset children (each child owns its own elapsed).
|
|
108
|
+
export function resetClock(clock) {
|
|
109
|
+
clock.elapsed = 0;
|
|
110
|
+
clock.deltaTime = 0;
|
|
111
|
+
}
|
|
112
|
+
// Resumes a locally-paused clock. The clock still receives a zero delta while any ancestor remains
|
|
113
|
+
// paused (see isClockEffectivelyPaused).
|
|
114
|
+
export function resumeClock(clock) {
|
|
115
|
+
clock.paused = false;
|
|
116
|
+
}
|
|
117
|
+
// Sets the clock's local time scale (1 = realtime, 0.5 = half speed, 2 = double, 0 = frozen without the
|
|
118
|
+
// paused flag). Composes with ancestors on the next advance — see getClockEffectiveScale.
|
|
119
|
+
export function setClockScale(clock, scale) {
|
|
120
|
+
clock.scale = scale;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=clock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.js","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clockSignals.d.ts","sourceRoot":"","sources":["../src/clockSignals.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAMrD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC,CAKpF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clockSignals.js","sourceRoot":"","sources":["../src/clockSignals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,sGAAsG;AACtG,0GAA0G;AAC1G,yGAAyG;AACzG,8FAA8F;AAC9F,MAAM,UAAU,kBAAkB,CAAC,KAAY;IAC7C,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC1B,KAAK,CAAC,MAAM,GAAG,YAAY,EAA+B,CAAC;IAC7D,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,CAAC;AACtB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './createClock';
|
|
4
|
-
export * from './disposeClock';
|
|
5
|
-
export * from './enableClockSignals';
|
|
6
|
-
export * from './getClockEffectiveScale';
|
|
7
|
-
export * from './getClockParent';
|
|
8
|
-
export * from './isClockEffectivelyPaused';
|
|
9
|
-
export * from './pauseClock';
|
|
10
|
-
export * from './resetClock';
|
|
11
|
-
export * from './setClockScale';
|
|
1
|
+
export * from './clock';
|
|
2
|
+
export * from './clockSignals';
|
|
12
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './createClock';
|
|
4
|
-
export * from './disposeClock';
|
|
5
|
-
export * from './enableClockSignals';
|
|
6
|
-
export * from './getClockEffectiveScale';
|
|
7
|
-
export * from './getClockParent';
|
|
8
|
-
export * from './isClockEffectivelyPaused';
|
|
9
|
-
export * from './pauseClock';
|
|
10
|
-
export * from './resetClock';
|
|
11
|
-
export * from './setClockScale';
|
|
1
|
+
export * from './clock';
|
|
2
|
+
export * from './clockSignals';
|
|
12
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/clock",
|
|
3
|
-
"version": "0.2.1-next.
|
|
3
|
+
"version": "0.2.1-next.585.c7219b8",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/flighthq/flight.git",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@flighthq/signals": "0.2.1-next.
|
|
36
|
-
"@flighthq/types": "0.2.1-next.
|
|
35
|
+
"@flighthq/signals": "0.2.1-next.585.c7219b8",
|
|
36
|
+
"@flighthq/types": "0.2.1-next.585.c7219b8"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"typescript": "^5.3.0"
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { connectSignal, hasSignalSlots } from '@flighthq/signals';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
addClockChild,
|
|
5
|
+
advanceClock,
|
|
6
|
+
createChildClock,
|
|
7
|
+
createClock,
|
|
8
|
+
disposeClock,
|
|
9
|
+
getClockEffectiveScale,
|
|
10
|
+
getClockParent,
|
|
11
|
+
isClockEffectivelyPaused,
|
|
12
|
+
pauseClock,
|
|
13
|
+
removeClockChild,
|
|
14
|
+
resetClock,
|
|
15
|
+
resumeClock,
|
|
16
|
+
setClockScale,
|
|
17
|
+
} from './clock';
|
|
18
|
+
import { enableClockSignals } from './clockSignals';
|
|
19
|
+
|
|
20
|
+
describe('addClockChild', () => {
|
|
21
|
+
it('attaches a child and sets its parent', () => {
|
|
22
|
+
const parent = createClock();
|
|
23
|
+
const child = createClock();
|
|
24
|
+
addClockChild(parent, child);
|
|
25
|
+
expect(child.parent).toBe(parent);
|
|
26
|
+
expect(parent.children).toEqual([child]);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('is a no-op when the child is already parented here', () => {
|
|
30
|
+
const parent = createClock();
|
|
31
|
+
const child = createClock();
|
|
32
|
+
addClockChild(parent, child);
|
|
33
|
+
addClockChild(parent, child);
|
|
34
|
+
expect(parent.children).toEqual([child]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('reparents, detaching from the previous parent first', () => {
|
|
38
|
+
const a = createClock();
|
|
39
|
+
const b = createClock();
|
|
40
|
+
const child = createClock();
|
|
41
|
+
addClockChild(a, child);
|
|
42
|
+
addClockChild(b, child);
|
|
43
|
+
expect(a.children).toEqual([]);
|
|
44
|
+
expect(b.children).toEqual([child]);
|
|
45
|
+
expect(child.parent).toBe(b);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('advanceClock', () => {
|
|
50
|
+
it('sets deltaTime to the real delta and accumulates elapsed on a realtime root', () => {
|
|
51
|
+
const clock = createClock();
|
|
52
|
+
advanceClock(clock, 0.5);
|
|
53
|
+
expect(clock.deltaTime).toBe(0.5);
|
|
54
|
+
expect(clock.elapsed).toBe(0.5);
|
|
55
|
+
advanceClock(clock, 0.25);
|
|
56
|
+
expect(clock.deltaTime).toBe(0.25);
|
|
57
|
+
expect(clock.elapsed).toBe(0.75);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('applies the local scale', () => {
|
|
61
|
+
const clock = createClock({ scale: 2 });
|
|
62
|
+
advanceClock(clock, 1);
|
|
63
|
+
expect(clock.deltaTime).toBe(2);
|
|
64
|
+
expect(clock.elapsed).toBe(2);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('feeds a zero delta while paused, freezing elapsed', () => {
|
|
68
|
+
const clock = createClock({ paused: true });
|
|
69
|
+
advanceClock(clock, 1);
|
|
70
|
+
expect(clock.deltaTime).toBe(0);
|
|
71
|
+
expect(clock.elapsed).toBe(0);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('composes scale down a 3-level hierarchy — grandparent to parent to child', () => {
|
|
75
|
+
const grandparent = createClock({ scale: 2 });
|
|
76
|
+
const parent = createChildClock(grandparent, { scale: 3 });
|
|
77
|
+
const child = createChildClock(parent, { scale: 0.5 });
|
|
78
|
+
advanceClock(grandparent, 1);
|
|
79
|
+
expect(grandparent.deltaTime).toBe(2); // 1 * 2
|
|
80
|
+
expect(parent.deltaTime).toBe(6); // 2 * 3
|
|
81
|
+
expect(child.deltaTime).toBe(3); // 6 * 0.5
|
|
82
|
+
expect(child.elapsed).toBe(3);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('composes scale down the hierarchy — a child rate is the product of the chain', () => {
|
|
86
|
+
const parent = createClock({ scale: 2 });
|
|
87
|
+
const child = createChildClock(parent, { scale: 0.5 });
|
|
88
|
+
advanceClock(parent, 1);
|
|
89
|
+
expect(parent.deltaTime).toBe(2);
|
|
90
|
+
expect(child.deltaTime).toBe(1); // 1 * 2 * 0.5
|
|
91
|
+
expect(child.elapsed).toBe(1);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('freezes a subtree when an ancestor is paused even if the child is running', () => {
|
|
95
|
+
const parent = createClock({ paused: true });
|
|
96
|
+
const child = createChildClock(parent);
|
|
97
|
+
advanceClock(parent, 1);
|
|
98
|
+
expect(parent.deltaTime).toBe(0);
|
|
99
|
+
expect(child.deltaTime).toBe(0);
|
|
100
|
+
expect(child.elapsed).toBe(0);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('emits onTick with the scaled delta when signals are enabled', () => {
|
|
104
|
+
const clock = createClock({ scale: 2 });
|
|
105
|
+
const received: number[] = [];
|
|
106
|
+
const onTick = enableClockSignals(clock);
|
|
107
|
+
connectSignal(onTick, (deltaTime) => received.push(deltaTime));
|
|
108
|
+
advanceClock(clock, 0.5);
|
|
109
|
+
expect(received).toEqual([1]); // 0.5 * 2
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('applies a negative deltaTime, producing negative deltaTime and decreasing elapsed', () => {
|
|
113
|
+
const clock = createClock();
|
|
114
|
+
advanceClock(clock, 1);
|
|
115
|
+
expect(clock.elapsed).toBe(1);
|
|
116
|
+
advanceClock(clock, -0.5);
|
|
117
|
+
expect(clock.deltaTime).toBe(-0.5);
|
|
118
|
+
expect(clock.elapsed).toBe(0.5);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('applies a negative scale, reversing the effective delta direction', () => {
|
|
122
|
+
const clock = createClock({ scale: -1 });
|
|
123
|
+
advanceClock(clock, 1);
|
|
124
|
+
expect(clock.deltaTime).toBe(-1);
|
|
125
|
+
expect(clock.elapsed).toBe(-1);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('does not emit or throw when signals are not enabled', () => {
|
|
129
|
+
const clock = createClock();
|
|
130
|
+
expect(() => advanceClock(clock, 1)).not.toThrow();
|
|
131
|
+
expect(clock.onTick).toBeNull();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe('createChildClock', () => {
|
|
136
|
+
it('creates a clock attached to the parent', () => {
|
|
137
|
+
const parent = createClock();
|
|
138
|
+
const child = createChildClock(parent);
|
|
139
|
+
expect(child.parent).toBe(parent);
|
|
140
|
+
expect(parent.children).toContain(child);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('applies options to the child', () => {
|
|
144
|
+
const parent = createClock();
|
|
145
|
+
const child = createChildClock(parent, { scale: 0.5, paused: true });
|
|
146
|
+
expect(child.scale).toBe(0.5);
|
|
147
|
+
expect(child.paused).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('createClock', () => {
|
|
152
|
+
it('defaults to realtime, running, zeroed, rootless, and signal-free', () => {
|
|
153
|
+
const clock = createClock();
|
|
154
|
+
expect(clock.scale).toBe(1);
|
|
155
|
+
expect(clock.paused).toBe(false);
|
|
156
|
+
expect(clock.deltaTime).toBe(0);
|
|
157
|
+
expect(clock.elapsed).toBe(0);
|
|
158
|
+
expect(clock.parent).toBeNull();
|
|
159
|
+
expect(clock.children).toEqual([]);
|
|
160
|
+
expect(clock.onTick).toBeNull();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('applies scale and paused options', () => {
|
|
164
|
+
const clock = createClock({ scale: 3, paused: true });
|
|
165
|
+
expect(clock.scale).toBe(3);
|
|
166
|
+
expect(clock.paused).toBe(true);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe('disposeClock', () => {
|
|
171
|
+
it('detaches the clock from its parent', () => {
|
|
172
|
+
const parent = createClock();
|
|
173
|
+
const clock = createClock();
|
|
174
|
+
addClockChild(parent, clock);
|
|
175
|
+
disposeClock(clock);
|
|
176
|
+
expect(parent.children).toEqual([]);
|
|
177
|
+
expect(clock.parent).toBeNull();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('releases its children, making each a root', () => {
|
|
181
|
+
const clock = createClock();
|
|
182
|
+
const child = createClock();
|
|
183
|
+
addClockChild(clock, child);
|
|
184
|
+
disposeClock(clock);
|
|
185
|
+
expect(clock.children).toEqual([]);
|
|
186
|
+
expect(child.parent).toBeNull();
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('clears onTick listeners', () => {
|
|
190
|
+
const clock = createClock();
|
|
191
|
+
const onTick = enableClockSignals(clock);
|
|
192
|
+
connectSignal(onTick, () => {});
|
|
193
|
+
expect(hasSignalSlots(onTick)).toBe(true);
|
|
194
|
+
disposeClock(clock);
|
|
195
|
+
expect(hasSignalSlots(onTick)).toBe(false);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('is safe on a rootless, childless, signal-free clock', () => {
|
|
199
|
+
const clock = createClock();
|
|
200
|
+
expect(() => disposeClock(clock)).not.toThrow();
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
describe('getClockEffectiveScale', () => {
|
|
205
|
+
it('returns the local scale for a root', () => {
|
|
206
|
+
expect(getClockEffectiveScale(createClock({ scale: 2 }))).toBe(2);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('multiplies through the ancestor chain', () => {
|
|
210
|
+
const a = createClock({ scale: 2 });
|
|
211
|
+
const b = createChildClock(a, { scale: 0.5 });
|
|
212
|
+
const c = createChildClock(b, { scale: 3 });
|
|
213
|
+
expect(getClockEffectiveScale(c)).toBe(3); // 2 * 0.5 * 3
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe('getClockParent', () => {
|
|
218
|
+
it('returns null for a root clock', () => {
|
|
219
|
+
expect(getClockParent(createClock())).toBeNull();
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('returns the parent for a child clock', () => {
|
|
223
|
+
const parent = createClock();
|
|
224
|
+
const child = createChildClock(parent);
|
|
225
|
+
expect(getClockParent(child)).toBe(parent);
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
describe('isClockEffectivelyPaused', () => {
|
|
230
|
+
it('is false for a running root', () => {
|
|
231
|
+
expect(isClockEffectivelyPaused(createClock())).toBe(false);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('is true when the clock itself is paused', () => {
|
|
235
|
+
expect(isClockEffectivelyPaused(createClock({ paused: true }))).toBe(true);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('is true when an ancestor is paused even if the clock is running', () => {
|
|
239
|
+
const parent = createClock({ paused: true });
|
|
240
|
+
const child = createChildClock(parent);
|
|
241
|
+
expect(child.paused).toBe(false);
|
|
242
|
+
expect(isClockEffectivelyPaused(child)).toBe(true);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
describe('pauseClock', () => {
|
|
247
|
+
it('sets paused to true', () => {
|
|
248
|
+
const clock = createClock();
|
|
249
|
+
pauseClock(clock);
|
|
250
|
+
expect(clock.paused).toBe(true);
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
describe('removeClockChild', () => {
|
|
255
|
+
it('detaches a child and clears its parent', () => {
|
|
256
|
+
const parent = createClock();
|
|
257
|
+
const child = createClock();
|
|
258
|
+
addClockChild(parent, child);
|
|
259
|
+
removeClockChild(parent, child);
|
|
260
|
+
expect(parent.children).toEqual([]);
|
|
261
|
+
expect(child.parent).toBeNull();
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('is a no-op when the child is not parented here', () => {
|
|
265
|
+
const parent = createClock();
|
|
266
|
+
const child = createClock();
|
|
267
|
+
expect(() => removeClockChild(parent, child)).not.toThrow();
|
|
268
|
+
expect(parent.children).toEqual([]);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
describe('resetClock', () => {
|
|
273
|
+
it('clears elapsed and deltaTime without touching scale or pause', () => {
|
|
274
|
+
const clock = createClock({ scale: 2 });
|
|
275
|
+
advanceClock(clock, 1);
|
|
276
|
+
resetClock(clock);
|
|
277
|
+
expect(clock.elapsed).toBe(0);
|
|
278
|
+
expect(clock.deltaTime).toBe(0);
|
|
279
|
+
expect(clock.scale).toBe(2);
|
|
280
|
+
expect(clock.paused).toBe(false);
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
describe('resumeClock', () => {
|
|
285
|
+
it('sets paused to false', () => {
|
|
286
|
+
const clock = createClock({ paused: true });
|
|
287
|
+
resumeClock(clock);
|
|
288
|
+
expect(clock.paused).toBe(false);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
describe('setClockScale', () => {
|
|
293
|
+
it('updates the local scale', () => {
|
|
294
|
+
const clock = createClock();
|
|
295
|
+
setClockScale(clock, 0.25);
|
|
296
|
+
expect(clock.scale).toBe(0.25);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createClock } from './
|
|
2
|
-
import { enableClockSignals } from './
|
|
1
|
+
import { createClock } from './clock';
|
|
2
|
+
import { enableClockSignals } from './clockSignals';
|
|
3
3
|
|
|
4
4
|
describe('enableClockSignals', () => {
|
|
5
5
|
it('allocates the onTick signal and returns it', () => {
|
package/dist/addClockChild.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"addClockChild.d.ts","sourceRoot":"","sources":["../src/addClockChild.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAI7C,wBAAgB,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAK/D;AAID,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAKlE"}
|
package/dist/addClockChild.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// Attaches `child` under `parent`, detaching it from any previous parent first (reparent-safe). After
|
|
2
|
-
// this, advancing `parent` cascades into `child`. A no-op if `child` is already parented here.
|
|
3
|
-
export function addClockChild(parent, child) {
|
|
4
|
-
if (child.parent === parent)
|
|
5
|
-
return;
|
|
6
|
-
if (child.parent !== null)
|
|
7
|
-
removeClockChild(child.parent, child);
|
|
8
|
-
child.parent = parent;
|
|
9
|
-
parent.children.push(child);
|
|
10
|
-
}
|
|
11
|
-
// Detaches `child` from `parent`, making it a root clock again. A no-op if `child` is not a child of
|
|
12
|
-
// `parent`.
|
|
13
|
-
export function removeClockChild(parent, child) {
|
|
14
|
-
const index = parent.children.indexOf(child);
|
|
15
|
-
if (index === -1)
|
|
16
|
-
return;
|
|
17
|
-
parent.children.splice(index, 1);
|
|
18
|
-
child.parent = null;
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=addClockChild.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"addClockChild.js","sourceRoot":"","sources":["../src/addClockChild.ts"],"names":[],"mappings":"AAEA,sGAAsG;AACtG,+FAA+F;AAC/F,MAAM,UAAU,aAAa,CAAC,MAAa,EAAE,KAAY;IACvD,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO;IACpC,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI;QAAE,gBAAgB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACjE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,qGAAqG;AACrG,YAAY;AACZ,MAAM,UAAU,gBAAgB,CAAC,MAAa,EAAE,KAAY;IAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7C,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO;IACzB,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACjC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;AACtB,CAAC"}
|
package/dist/advanceClock.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"advanceClock.d.ts","sourceRoot":"","sources":["../src/advanceClock.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAQ7C,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CASrE"}
|
package/dist/advanceClock.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { emitSignal } from '@flighthq/signals';
|
|
2
|
-
// Advances a clock tree by one step. `deltaSeconds` is the real elapsed seconds for a root clock (the
|
|
3
|
-
// value the frame loop supplies); the cascade feeds each child its parent's already-scaled delta. Each
|
|
4
|
-
// clock's scaled delta is `paused ? 0 : deltaSeconds * scale`; that becomes its deltaTime, accumulates
|
|
5
|
-
// into elapsed, emits its (opt-in) onTick, and drives its children — so scale and pause compose down the
|
|
6
|
-
// whole subtree in one pass. Pre-order: a clock's onTick fires before its children advance. Call once per
|
|
7
|
-
// frame on the root: advanceClock(root, dtSeconds).
|
|
8
|
-
export function advanceClock(clock, deltaSeconds) {
|
|
9
|
-
const scaledDelta = clock.paused ? 0 : deltaSeconds * clock.scale;
|
|
10
|
-
clock.deltaTime = scaledDelta;
|
|
11
|
-
clock.elapsed += scaledDelta;
|
|
12
|
-
if (clock.onTick !== null)
|
|
13
|
-
emitSignal(clock.onTick, scaledDelta);
|
|
14
|
-
const children = clock.children;
|
|
15
|
-
for (let i = 0; i < children.length; i++) {
|
|
16
|
-
advanceClock(children[i], scaledDelta);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=advanceClock.js.map
|
package/dist/advanceClock.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"advanceClock.js","sourceRoot":"","sources":["../src/advanceClock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,sGAAsG;AACtG,uGAAuG;AACvG,uGAAuG;AACvG,yGAAyG;AACzG,0GAA0G;AAC1G,oDAAoD;AACpD,MAAM,UAAU,YAAY,CAAC,KAAY,EAAE,YAAoB;IAC7D,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC;IAClE,KAAK,CAAC,SAAS,GAAG,WAAW,CAAC;IAC9B,KAAK,CAAC,OAAO,IAAI,WAAW,CAAC;IAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI;QAAE,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACjE,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IACzC,CAAC;AACH,CAAC"}
|
package/dist/createClock.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { Clock, ClockOptions } from '@flighthq/types';
|
|
2
|
-
export declare function createChildClock(parent: Clock, options?: Readonly<ClockOptions>): Clock;
|
|
3
|
-
export declare function createClock(options?: Readonly<ClockOptions>): Clock;
|
|
4
|
-
//# sourceMappingURL=createClock.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createClock.d.ts","sourceRoot":"","sources":["../src/createClock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAM3D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,KAAK,CAIvF;AAID,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,KAAK,CAUnE"}
|
package/dist/createClock.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { addClockChild } from './addClockChild';
|
|
2
|
-
// Allocates a child clock and attaches it to `parent` in one step. Equivalent to createClock followed by
|
|
3
|
-
// addClockChild; the child inherits `parent`'s scale and pause state through the advanceClock cascade.
|
|
4
|
-
export function createChildClock(parent, options) {
|
|
5
|
-
const child = createClock(options);
|
|
6
|
-
addClockChild(parent, child);
|
|
7
|
-
return child;
|
|
8
|
-
}
|
|
9
|
-
// Allocates a root clock (no parent). Defaults to realtime and running; pass options to start scaled or
|
|
10
|
-
// paused. Drive it each frame with advanceClock(clock, dtSeconds).
|
|
11
|
-
export function createClock(options) {
|
|
12
|
-
return {
|
|
13
|
-
scale: options?.scale ?? 1,
|
|
14
|
-
paused: options?.paused ?? false,
|
|
15
|
-
deltaTime: 0,
|
|
16
|
-
elapsed: 0,
|
|
17
|
-
parent: null,
|
|
18
|
-
children: [],
|
|
19
|
-
onTick: null,
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=createClock.js.map
|
package/dist/createClock.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createClock.js","sourceRoot":"","sources":["../src/createClock.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,yGAAyG;AACzG,uGAAuG;AACvG,MAAM,UAAU,gBAAgB,CAAC,MAAa,EAAE,OAAgC;IAC9E,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACnC,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC7B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wGAAwG;AACxG,mEAAmE;AACnE,MAAM,UAAU,WAAW,CAAC,OAAgC;IAC1D,OAAO;QACL,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;QAC1B,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,KAAK;QAChC,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,IAAI;KACb,CAAC;AACJ,CAAC"}
|
package/dist/disposeClock.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"disposeClock.d.ts","sourceRoot":"","sources":["../src/disposeClock.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAQ7C,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAQ/C"}
|
package/dist/disposeClock.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { clearSignal } from '@flighthq/signals';
|
|
2
|
-
import { removeClockChild } from './addClockChild';
|
|
3
|
-
// Detaches a clock from its parent, releases its children, and drops any onTick listeners so nothing
|
|
4
|
-
// keeps the subtree — or the clock's subscribers — reachable through it: the parent no longer references
|
|
5
|
-
// this clock, each child becomes a root, and the onTick slot list is cleared. The clock is then plain
|
|
6
|
-
// GC-managed memory (there is no GPU or native resource to free — that would be destroy*).
|
|
7
|
-
export function disposeClock(clock) {
|
|
8
|
-
if (clock.parent !== null)
|
|
9
|
-
removeClockChild(clock.parent, clock);
|
|
10
|
-
const children = clock.children;
|
|
11
|
-
for (let i = 0; i < children.length; i++) {
|
|
12
|
-
children[i].parent = null;
|
|
13
|
-
}
|
|
14
|
-
children.length = 0;
|
|
15
|
-
if (clock.onTick !== null)
|
|
16
|
-
clearSignal(clock.onTick);
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=disposeClock.js.map
|
package/dist/disposeClock.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"disposeClock.js","sourceRoot":"","sources":["../src/disposeClock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,qGAAqG;AACrG,yGAAyG;AACzG,sGAAsG;AACtG,2FAA2F;AAC3F,MAAM,UAAU,YAAY,CAAC,KAAY;IACvC,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI;QAAE,gBAAgB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACjE,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC;IAC5B,CAAC;IACD,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IACpB,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI;QAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"enableClockSignals.d.ts","sourceRoot":"","sources":["../src/enableClockSignals.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAMrD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC,CAKpF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"enableClockSignals.js","sourceRoot":"","sources":["../src/enableClockSignals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,sGAAsG;AACtG,0GAA0G;AAC1G,yGAAyG;AACzG,8FAA8F;AAC9F,MAAM,UAAU,kBAAkB,CAAC,KAAY;IAC7C,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC1B,KAAK,CAAC,MAAM,GAAG,YAAY,EAA+B,CAAC;IAC7D,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,CAAC;AACtB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getClockEffectiveScale.d.ts","sourceRoot":"","sources":["../src/getClockEffectiveScale.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAK7C,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,MAAM,CAQrE"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// The clock's realtime rate accounting for the hierarchy: the product of its own scale and every
|
|
2
|
-
// ancestor's scale. A root clock's effective scale is just its own. This is what `deltaTime` divided by
|
|
3
|
-
// the loop's real delta would equal (when nothing in the chain is paused).
|
|
4
|
-
export function getClockEffectiveScale(clock) {
|
|
5
|
-
let scale = clock.scale;
|
|
6
|
-
let current = clock.parent;
|
|
7
|
-
while (current !== null) {
|
|
8
|
-
scale *= current.scale;
|
|
9
|
-
current = current.parent;
|
|
10
|
-
}
|
|
11
|
-
return scale;
|
|
12
|
-
}
|
|
13
|
-
//# sourceMappingURL=getClockEffectiveScale.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getClockEffectiveScale.js","sourceRoot":"","sources":["../src/getClockEffectiveScale.ts"],"names":[],"mappings":"AAEA,iGAAiG;AACjG,wGAAwG;AACxG,2EAA2E;AAC3E,MAAM,UAAU,sBAAsB,CAAC,KAAsB;IAC3D,IAAI,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACxB,IAAI,OAAO,GAA2B,KAAK,CAAC,MAAM,CAAC;IACnD,OAAO,OAAO,KAAK,IAAI,EAAE,CAAC;QACxB,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC;QACvB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/getClockParent.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getClockParent.d.ts","sourceRoot":"","sources":["../src/getClockParent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAI7C,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,CAEnE"}
|
package/dist/getClockParent.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// The clock's parent, or null if it is a root. Convenience accessor for the `parent` field; hierarchy is
|
|
2
|
-
// changed through addClockChild / removeClockChild, not by assigning this.
|
|
3
|
-
export function getClockParent(clock) {
|
|
4
|
-
return clock.parent;
|
|
5
|
-
}
|
|
6
|
-
//# sourceMappingURL=getClockParent.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getClockParent.js","sourceRoot":"","sources":["../src/getClockParent.ts"],"names":[],"mappings":"AAEA,yGAAyG;AACzG,2EAA2E;AAC3E,MAAM,UAAU,cAAc,CAAC,KAAsB;IACnD,OAAO,KAAK,CAAC,MAAM,CAAC;AACtB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"isClockEffectivelyPaused.d.ts","sourceRoot":"","sources":["../src/isClockEffectivelyPaused.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAI7C,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,OAAO,CAOxE"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// Whether this clock receives a zero delta on the next advance: true if the clock itself or any ancestor
|
|
2
|
-
// is paused. A clock can be locally running yet effectively paused because a parent is paused.
|
|
3
|
-
export function isClockEffectivelyPaused(clock) {
|
|
4
|
-
let current = clock;
|
|
5
|
-
while (current !== null) {
|
|
6
|
-
if (current.paused)
|
|
7
|
-
return true;
|
|
8
|
-
current = current.parent;
|
|
9
|
-
}
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
//# sourceMappingURL=isClockEffectivelyPaused.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"isClockEffectivelyPaused.js","sourceRoot":"","sources":["../src/isClockEffectivelyPaused.ts"],"names":[],"mappings":"AAEA,yGAAyG;AACzG,+FAA+F;AAC/F,MAAM,UAAU,wBAAwB,CAAC,KAAsB;IAC7D,IAAI,OAAO,GAA2B,KAAK,CAAC;IAC5C,OAAO,OAAO,KAAK,IAAI,EAAE,CAAC;QACxB,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAChC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/pauseClock.d.ts
DELETED
package/dist/pauseClock.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pauseClock.d.ts","sourceRoot":"","sources":["../src/pauseClock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAI7C,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAE7C;AAID,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAE9C"}
|
package/dist/pauseClock.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Pauses the clock: it and its whole subtree receive a zero delta on subsequent advances, so elapsed
|
|
2
|
-
// freezes until resumed. Local state — a child paused this way stays paused even if its parent resumes.
|
|
3
|
-
export function pauseClock(clock) {
|
|
4
|
-
clock.paused = true;
|
|
5
|
-
}
|
|
6
|
-
// Resumes a locally-paused clock. The clock still receives a zero delta while any ancestor remains
|
|
7
|
-
// paused (see isClockEffectivelyPaused).
|
|
8
|
-
export function resumeClock(clock) {
|
|
9
|
-
clock.paused = false;
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=pauseClock.js.map
|
package/dist/pauseClock.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pauseClock.js","sourceRoot":"","sources":["../src/pauseClock.ts"],"names":[],"mappings":"AAEA,qGAAqG;AACrG,wGAAwG;AACxG,MAAM,UAAU,UAAU,CAAC,KAAY;IACrC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;AACtB,CAAC;AAED,mGAAmG;AACnG,yCAAyC;AACzC,MAAM,UAAU,WAAW,CAAC,KAAY;IACtC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;AACvB,CAAC"}
|
package/dist/resetClock.d.ts
DELETED
package/dist/resetClock.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resetClock.d.ts","sourceRoot":"","sources":["../src/resetClock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAI7C,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAG7C"}
|
package/dist/resetClock.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
// Clears the clock's accumulated time back to the start: elapsed and deltaTime become 0. Does not touch
|
|
2
|
-
// scale, pause, or the hierarchy, and does not reset children (each child owns its own elapsed).
|
|
3
|
-
export function resetClock(clock) {
|
|
4
|
-
clock.elapsed = 0;
|
|
5
|
-
clock.deltaTime = 0;
|
|
6
|
-
}
|
|
7
|
-
//# sourceMappingURL=resetClock.js.map
|
package/dist/resetClock.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resetClock.js","sourceRoot":"","sources":["../src/resetClock.ts"],"names":[],"mappings":"AAEA,wGAAwG;AACxG,iGAAiG;AACjG,MAAM,UAAU,UAAU,CAAC,KAAY;IACrC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC;IAClB,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;AACtB,CAAC"}
|
package/dist/setClockScale.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"setClockScale.d.ts","sourceRoot":"","sources":["../src/setClockScale.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAI7C,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE/D"}
|
package/dist/setClockScale.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// Sets the clock's local time scale (1 = realtime, 0.5 = half speed, 2 = double, 0 = frozen without the
|
|
2
|
-
// paused flag). Composes with ancestors on the next advance — see getClockEffectiveScale.
|
|
3
|
-
export function setClockScale(clock, scale) {
|
|
4
|
-
clock.scale = scale;
|
|
5
|
-
}
|
|
6
|
-
//# sourceMappingURL=setClockScale.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"setClockScale.js","sourceRoot":"","sources":["../src/setClockScale.ts"],"names":[],"mappings":"AAEA,wGAAwG;AACxG,0FAA0F;AAC1F,MAAM,UAAU,aAAa,CAAC,KAAY,EAAE,KAAa;IACvD,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;AACtB,CAAC"}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { addClockChild, removeClockChild } from './addClockChild';
|
|
2
|
-
import { createClock } from './createClock';
|
|
3
|
-
|
|
4
|
-
describe('addClockChild', () => {
|
|
5
|
-
it('attaches a child and sets its parent', () => {
|
|
6
|
-
const parent = createClock();
|
|
7
|
-
const child = createClock();
|
|
8
|
-
addClockChild(parent, child);
|
|
9
|
-
expect(child.parent).toBe(parent);
|
|
10
|
-
expect(parent.children).toEqual([child]);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('is a no-op when the child is already parented here', () => {
|
|
14
|
-
const parent = createClock();
|
|
15
|
-
const child = createClock();
|
|
16
|
-
addClockChild(parent, child);
|
|
17
|
-
addClockChild(parent, child);
|
|
18
|
-
expect(parent.children).toEqual([child]);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('reparents, detaching from the previous parent first', () => {
|
|
22
|
-
const a = createClock();
|
|
23
|
-
const b = createClock();
|
|
24
|
-
const child = createClock();
|
|
25
|
-
addClockChild(a, child);
|
|
26
|
-
addClockChild(b, child);
|
|
27
|
-
expect(a.children).toEqual([]);
|
|
28
|
-
expect(b.children).toEqual([child]);
|
|
29
|
-
expect(child.parent).toBe(b);
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
describe('removeClockChild', () => {
|
|
34
|
-
it('detaches a child and clears its parent', () => {
|
|
35
|
-
const parent = createClock();
|
|
36
|
-
const child = createClock();
|
|
37
|
-
addClockChild(parent, child);
|
|
38
|
-
removeClockChild(parent, child);
|
|
39
|
-
expect(parent.children).toEqual([]);
|
|
40
|
-
expect(child.parent).toBeNull();
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('is a no-op when the child is not parented here', () => {
|
|
44
|
-
const parent = createClock();
|
|
45
|
-
const child = createClock();
|
|
46
|
-
expect(() => removeClockChild(parent, child)).not.toThrow();
|
|
47
|
-
expect(parent.children).toEqual([]);
|
|
48
|
-
});
|
|
49
|
-
});
|
package/src/advanceClock.test.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { connectSignal } from '@flighthq/signals';
|
|
2
|
-
|
|
3
|
-
import { advanceClock } from './advanceClock';
|
|
4
|
-
import { createChildClock, createClock } from './createClock';
|
|
5
|
-
import { enableClockSignals } from './enableClockSignals';
|
|
6
|
-
|
|
7
|
-
describe('advanceClock', () => {
|
|
8
|
-
it('sets deltaTime to the real delta and accumulates elapsed on a realtime root', () => {
|
|
9
|
-
const clock = createClock();
|
|
10
|
-
advanceClock(clock, 0.5);
|
|
11
|
-
expect(clock.deltaTime).toBe(0.5);
|
|
12
|
-
expect(clock.elapsed).toBe(0.5);
|
|
13
|
-
advanceClock(clock, 0.25);
|
|
14
|
-
expect(clock.deltaTime).toBe(0.25);
|
|
15
|
-
expect(clock.elapsed).toBe(0.75);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('applies the local scale', () => {
|
|
19
|
-
const clock = createClock({ scale: 2 });
|
|
20
|
-
advanceClock(clock, 1);
|
|
21
|
-
expect(clock.deltaTime).toBe(2);
|
|
22
|
-
expect(clock.elapsed).toBe(2);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('feeds a zero delta while paused, freezing elapsed', () => {
|
|
26
|
-
const clock = createClock({ paused: true });
|
|
27
|
-
advanceClock(clock, 1);
|
|
28
|
-
expect(clock.deltaTime).toBe(0);
|
|
29
|
-
expect(clock.elapsed).toBe(0);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('composes scale down a 3-level hierarchy — grandparent to parent to child', () => {
|
|
33
|
-
const grandparent = createClock({ scale: 2 });
|
|
34
|
-
const parent = createChildClock(grandparent, { scale: 3 });
|
|
35
|
-
const child = createChildClock(parent, { scale: 0.5 });
|
|
36
|
-
advanceClock(grandparent, 1);
|
|
37
|
-
expect(grandparent.deltaTime).toBe(2); // 1 * 2
|
|
38
|
-
expect(parent.deltaTime).toBe(6); // 2 * 3
|
|
39
|
-
expect(child.deltaTime).toBe(3); // 6 * 0.5
|
|
40
|
-
expect(child.elapsed).toBe(3);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('composes scale down the hierarchy — a child rate is the product of the chain', () => {
|
|
44
|
-
const parent = createClock({ scale: 2 });
|
|
45
|
-
const child = createChildClock(parent, { scale: 0.5 });
|
|
46
|
-
advanceClock(parent, 1);
|
|
47
|
-
expect(parent.deltaTime).toBe(2);
|
|
48
|
-
expect(child.deltaTime).toBe(1); // 1 * 2 * 0.5
|
|
49
|
-
expect(child.elapsed).toBe(1);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('freezes a subtree when an ancestor is paused even if the child is running', () => {
|
|
53
|
-
const parent = createClock({ paused: true });
|
|
54
|
-
const child = createChildClock(parent);
|
|
55
|
-
advanceClock(parent, 1);
|
|
56
|
-
expect(parent.deltaTime).toBe(0);
|
|
57
|
-
expect(child.deltaTime).toBe(0);
|
|
58
|
-
expect(child.elapsed).toBe(0);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('emits onTick with the scaled delta when signals are enabled', () => {
|
|
62
|
-
const clock = createClock({ scale: 2 });
|
|
63
|
-
const received: number[] = [];
|
|
64
|
-
const onTick = enableClockSignals(clock);
|
|
65
|
-
connectSignal(onTick, (deltaTime) => received.push(deltaTime));
|
|
66
|
-
advanceClock(clock, 0.5);
|
|
67
|
-
expect(received).toEqual([1]); // 0.5 * 2
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('applies a negative deltaTime, producing negative deltaTime and decreasing elapsed', () => {
|
|
71
|
-
const clock = createClock();
|
|
72
|
-
advanceClock(clock, 1);
|
|
73
|
-
expect(clock.elapsed).toBe(1);
|
|
74
|
-
advanceClock(clock, -0.5);
|
|
75
|
-
expect(clock.deltaTime).toBe(-0.5);
|
|
76
|
-
expect(clock.elapsed).toBe(0.5);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('applies a negative scale, reversing the effective delta direction', () => {
|
|
80
|
-
const clock = createClock({ scale: -1 });
|
|
81
|
-
advanceClock(clock, 1);
|
|
82
|
-
expect(clock.deltaTime).toBe(-1);
|
|
83
|
-
expect(clock.elapsed).toBe(-1);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('does not emit or throw when signals are not enabled', () => {
|
|
87
|
-
const clock = createClock();
|
|
88
|
-
expect(() => advanceClock(clock, 1)).not.toThrow();
|
|
89
|
-
expect(clock.onTick).toBeNull();
|
|
90
|
-
});
|
|
91
|
-
});
|
package/src/createClock.test.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { createChildClock, createClock } from './createClock';
|
|
2
|
-
|
|
3
|
-
describe('createChildClock', () => {
|
|
4
|
-
it('creates a clock attached to the parent', () => {
|
|
5
|
-
const parent = createClock();
|
|
6
|
-
const child = createChildClock(parent);
|
|
7
|
-
expect(child.parent).toBe(parent);
|
|
8
|
-
expect(parent.children).toContain(child);
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('applies options to the child', () => {
|
|
12
|
-
const parent = createClock();
|
|
13
|
-
const child = createChildClock(parent, { scale: 0.5, paused: true });
|
|
14
|
-
expect(child.scale).toBe(0.5);
|
|
15
|
-
expect(child.paused).toBe(true);
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
describe('createClock', () => {
|
|
20
|
-
it('defaults to realtime, running, zeroed, rootless, and signal-free', () => {
|
|
21
|
-
const clock = createClock();
|
|
22
|
-
expect(clock.scale).toBe(1);
|
|
23
|
-
expect(clock.paused).toBe(false);
|
|
24
|
-
expect(clock.deltaTime).toBe(0);
|
|
25
|
-
expect(clock.elapsed).toBe(0);
|
|
26
|
-
expect(clock.parent).toBeNull();
|
|
27
|
-
expect(clock.children).toEqual([]);
|
|
28
|
-
expect(clock.onTick).toBeNull();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('applies scale and paused options', () => {
|
|
32
|
-
const clock = createClock({ scale: 3, paused: true });
|
|
33
|
-
expect(clock.scale).toBe(3);
|
|
34
|
-
expect(clock.paused).toBe(true);
|
|
35
|
-
});
|
|
36
|
-
});
|
package/src/disposeClock.test.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { connectSignal, hasSignalSlots } from '@flighthq/signals';
|
|
2
|
-
|
|
3
|
-
import { addClockChild } from './addClockChild';
|
|
4
|
-
import { createClock } from './createClock';
|
|
5
|
-
import { disposeClock } from './disposeClock';
|
|
6
|
-
import { enableClockSignals } from './enableClockSignals';
|
|
7
|
-
|
|
8
|
-
describe('disposeClock', () => {
|
|
9
|
-
it('detaches the clock from its parent', () => {
|
|
10
|
-
const parent = createClock();
|
|
11
|
-
const clock = createClock();
|
|
12
|
-
addClockChild(parent, clock);
|
|
13
|
-
disposeClock(clock);
|
|
14
|
-
expect(parent.children).toEqual([]);
|
|
15
|
-
expect(clock.parent).toBeNull();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('releases its children, making each a root', () => {
|
|
19
|
-
const clock = createClock();
|
|
20
|
-
const child = createClock();
|
|
21
|
-
addClockChild(clock, child);
|
|
22
|
-
disposeClock(clock);
|
|
23
|
-
expect(clock.children).toEqual([]);
|
|
24
|
-
expect(child.parent).toBeNull();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it('clears onTick listeners', () => {
|
|
28
|
-
const clock = createClock();
|
|
29
|
-
const onTick = enableClockSignals(clock);
|
|
30
|
-
connectSignal(onTick, () => {});
|
|
31
|
-
expect(hasSignalSlots(onTick)).toBe(true);
|
|
32
|
-
disposeClock(clock);
|
|
33
|
-
expect(hasSignalSlots(onTick)).toBe(false);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('is safe on a rootless, childless, signal-free clock', () => {
|
|
37
|
-
const clock = createClock();
|
|
38
|
-
expect(() => disposeClock(clock)).not.toThrow();
|
|
39
|
-
});
|
|
40
|
-
});
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { createChildClock, createClock } from './createClock';
|
|
2
|
-
import { getClockEffectiveScale } from './getClockEffectiveScale';
|
|
3
|
-
|
|
4
|
-
describe('getClockEffectiveScale', () => {
|
|
5
|
-
it('returns the local scale for a root', () => {
|
|
6
|
-
expect(getClockEffectiveScale(createClock({ scale: 2 }))).toBe(2);
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
it('multiplies through the ancestor chain', () => {
|
|
10
|
-
const a = createClock({ scale: 2 });
|
|
11
|
-
const b = createChildClock(a, { scale: 0.5 });
|
|
12
|
-
const c = createChildClock(b, { scale: 3 });
|
|
13
|
-
expect(getClockEffectiveScale(c)).toBe(3); // 2 * 0.5 * 3
|
|
14
|
-
});
|
|
15
|
-
});
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { createChildClock, createClock } from './createClock';
|
|
2
|
-
import { getClockParent } from './getClockParent';
|
|
3
|
-
|
|
4
|
-
describe('getClockParent', () => {
|
|
5
|
-
it('returns null for a root clock', () => {
|
|
6
|
-
expect(getClockParent(createClock())).toBeNull();
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
it('returns the parent for a child clock', () => {
|
|
10
|
-
const parent = createClock();
|
|
11
|
-
const child = createChildClock(parent);
|
|
12
|
-
expect(getClockParent(child)).toBe(parent);
|
|
13
|
-
});
|
|
14
|
-
});
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { createChildClock, createClock } from './createClock';
|
|
2
|
-
import { isClockEffectivelyPaused } from './isClockEffectivelyPaused';
|
|
3
|
-
|
|
4
|
-
describe('isClockEffectivelyPaused', () => {
|
|
5
|
-
it('is false for a running root', () => {
|
|
6
|
-
expect(isClockEffectivelyPaused(createClock())).toBe(false);
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
it('is true when the clock itself is paused', () => {
|
|
10
|
-
expect(isClockEffectivelyPaused(createClock({ paused: true }))).toBe(true);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('is true when an ancestor is paused even if the clock is running', () => {
|
|
14
|
-
const parent = createClock({ paused: true });
|
|
15
|
-
const child = createChildClock(parent);
|
|
16
|
-
expect(child.paused).toBe(false);
|
|
17
|
-
expect(isClockEffectivelyPaused(child)).toBe(true);
|
|
18
|
-
});
|
|
19
|
-
});
|
package/src/pauseClock.test.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { createClock } from './createClock';
|
|
2
|
-
import { pauseClock, resumeClock } from './pauseClock';
|
|
3
|
-
|
|
4
|
-
describe('pauseClock', () => {
|
|
5
|
-
it('sets paused to true', () => {
|
|
6
|
-
const clock = createClock();
|
|
7
|
-
pauseClock(clock);
|
|
8
|
-
expect(clock.paused).toBe(true);
|
|
9
|
-
});
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
describe('resumeClock', () => {
|
|
13
|
-
it('sets paused to false', () => {
|
|
14
|
-
const clock = createClock({ paused: true });
|
|
15
|
-
resumeClock(clock);
|
|
16
|
-
expect(clock.paused).toBe(false);
|
|
17
|
-
});
|
|
18
|
-
});
|
package/src/resetClock.test.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { advanceClock } from './advanceClock';
|
|
2
|
-
import { createClock } from './createClock';
|
|
3
|
-
import { resetClock } from './resetClock';
|
|
4
|
-
|
|
5
|
-
describe('resetClock', () => {
|
|
6
|
-
it('clears elapsed and deltaTime without touching scale or pause', () => {
|
|
7
|
-
const clock = createClock({ scale: 2 });
|
|
8
|
-
advanceClock(clock, 1);
|
|
9
|
-
resetClock(clock);
|
|
10
|
-
expect(clock.elapsed).toBe(0);
|
|
11
|
-
expect(clock.deltaTime).toBe(0);
|
|
12
|
-
expect(clock.scale).toBe(2);
|
|
13
|
-
expect(clock.paused).toBe(false);
|
|
14
|
-
});
|
|
15
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { createClock } from './createClock';
|
|
2
|
-
import { setClockScale } from './setClockScale';
|
|
3
|
-
|
|
4
|
-
describe('setClockScale', () => {
|
|
5
|
-
it('updates the local scale', () => {
|
|
6
|
-
const clock = createClock();
|
|
7
|
-
setClockScale(clock, 0.25);
|
|
8
|
-
expect(clock.scale).toBe(0.25);
|
|
9
|
-
});
|
|
10
|
-
});
|