@flighthq/clock 0.1.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/dist/addClockChild.d.ts +4 -0
- package/dist/addClockChild.d.ts.map +1 -0
- package/dist/addClockChild.js +20 -0
- package/dist/addClockChild.js.map +1 -0
- package/dist/advanceClock.d.ts +3 -0
- package/dist/advanceClock.d.ts.map +1 -0
- package/dist/advanceClock.js +19 -0
- package/dist/advanceClock.js.map +1 -0
- package/dist/createClock.d.ts +4 -0
- package/dist/createClock.d.ts.map +1 -0
- package/dist/createClock.js +22 -0
- package/dist/createClock.js.map +1 -0
- package/dist/disposeClock.d.ts +3 -0
- package/dist/disposeClock.d.ts.map +1 -0
- package/dist/disposeClock.js +18 -0
- package/dist/disposeClock.js.map +1 -0
- package/dist/enableClockSignals.d.ts +3 -0
- package/dist/enableClockSignals.d.ts.map +1 -0
- package/dist/enableClockSignals.js +12 -0
- package/dist/enableClockSignals.js.map +1 -0
- package/dist/getClockEffectiveScale.d.ts +3 -0
- package/dist/getClockEffectiveScale.d.ts.map +1 -0
- package/dist/getClockEffectiveScale.js +13 -0
- package/dist/getClockEffectiveScale.js.map +1 -0
- package/dist/getClockParent.d.ts +3 -0
- package/dist/getClockParent.d.ts.map +1 -0
- package/dist/getClockParent.js +6 -0
- package/dist/getClockParent.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/isClockEffectivelyPaused.d.ts +3 -0
- package/dist/isClockEffectivelyPaused.d.ts.map +1 -0
- package/dist/isClockEffectivelyPaused.js +12 -0
- package/dist/isClockEffectivelyPaused.js.map +1 -0
- package/dist/pauseClock.d.ts +4 -0
- package/dist/pauseClock.d.ts.map +1 -0
- package/dist/pauseClock.js +11 -0
- package/dist/pauseClock.js.map +1 -0
- package/dist/resetClock.d.ts +3 -0
- package/dist/resetClock.d.ts.map +1 -0
- package/dist/resetClock.js +7 -0
- package/dist/resetClock.js.map +1 -0
- package/dist/setClockScale.d.ts +3 -0
- package/dist/setClockScale.d.ts.map +1 -0
- package/dist/setClockScale.js +6 -0
- package/dist/setClockScale.js.map +1 -0
- package/package.json +38 -0
- package/src/addClockChild.test.ts +49 -0
- package/src/advanceClock.test.ts +64 -0
- package/src/createClock.test.ts +36 -0
- package/src/disposeClock.test.ts +40 -0
- package/src/enableClockSignals.test.ts +18 -0
- package/src/getClockEffectiveScale.test.ts +15 -0
- package/src/getClockParent.test.ts +14 -0
- package/src/isClockEffectivelyPaused.test.ts +19 -0
- package/src/pauseClock.test.ts +18 -0
- package/src/resetClock.test.ts +15 -0
- package/src/setClockScale.test.ts +10 -0
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createSignal } from '@flighthq/signals';
|
|
2
|
+
// Opts the clock into the onTick signal, allocating it on first call and returning it (idempotent — a
|
|
3
|
+
// second call returns the same signal). onTick emits the clock's scaled deltaTime on every advance, so it
|
|
4
|
+
// plugs straight into signals' rate helpers, e.g. connectSignalAtFrameRate(clock.onTick, 30, slot). Bare
|
|
5
|
+
// clocks that never call this keep onTick null and pay no signal allocation or dispatch cost.
|
|
6
|
+
export function enableClockSignals(clock) {
|
|
7
|
+
if (clock.onTick === null) {
|
|
8
|
+
clock.onTick = createSignal();
|
|
9
|
+
}
|
|
10
|
+
return clock.onTick;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=enableClockSignals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './addClockChild';
|
|
2
|
+
export * from './advanceClock';
|
|
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';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './addClockChild';
|
|
2
|
+
export * from './advanceClock';
|
|
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';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flighthq/clock",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"src/**/*.test.ts",
|
|
16
|
+
"!dist/**/*.test.js",
|
|
17
|
+
"!dist/**/*.test.d.ts",
|
|
18
|
+
"!dist/**/*.test.js.map",
|
|
19
|
+
"!dist/**/*.test.d.ts.map"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc -b",
|
|
23
|
+
"clean": "tsc -b --clean",
|
|
24
|
+
"test": "vitest run --config vitest.config.ts",
|
|
25
|
+
"test:watch": "vitest --watch --config vitest.config.ts",
|
|
26
|
+
"prepack": "npm run clean && npm run clean:dist && npm run build",
|
|
27
|
+
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@flighthq/signals": "0.1.0",
|
|
31
|
+
"@flighthq/types": "0.1.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"typescript": "^5.3.0"
|
|
35
|
+
},
|
|
36
|
+
"description": "Hierarchical, pausable, scalable time primitive for time-driven systems",
|
|
37
|
+
"sideEffects": false
|
|
38
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
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 the hierarchy — a child rate is the product of the chain', () => {
|
|
33
|
+
const parent = createClock({ scale: 2 });
|
|
34
|
+
const child = createChildClock(parent, { scale: 0.5 });
|
|
35
|
+
advanceClock(parent, 1);
|
|
36
|
+
expect(parent.deltaTime).toBe(2);
|
|
37
|
+
expect(child.deltaTime).toBe(1); // 1 * 2 * 0.5
|
|
38
|
+
expect(child.elapsed).toBe(1);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('freezes a subtree when an ancestor is paused even if the child is running', () => {
|
|
42
|
+
const parent = createClock({ paused: true });
|
|
43
|
+
const child = createChildClock(parent);
|
|
44
|
+
advanceClock(parent, 1);
|
|
45
|
+
expect(parent.deltaTime).toBe(0);
|
|
46
|
+
expect(child.deltaTime).toBe(0);
|
|
47
|
+
expect(child.elapsed).toBe(0);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('emits onTick with the scaled delta when signals are enabled', () => {
|
|
51
|
+
const clock = createClock({ scale: 2 });
|
|
52
|
+
const received: number[] = [];
|
|
53
|
+
const onTick = enableClockSignals(clock);
|
|
54
|
+
connectSignal(onTick, (deltaTime) => received.push(deltaTime));
|
|
55
|
+
advanceClock(clock, 0.5);
|
|
56
|
+
expect(received).toEqual([1]); // 0.5 * 2
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('does not emit or throw when signals are not enabled', () => {
|
|
60
|
+
const clock = createClock();
|
|
61
|
+
expect(() => advanceClock(clock, 1)).not.toThrow();
|
|
62
|
+
expect(clock.onTick).toBeNull();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createClock } from './createClock';
|
|
2
|
+
import { enableClockSignals } from './enableClockSignals';
|
|
3
|
+
|
|
4
|
+
describe('enableClockSignals', () => {
|
|
5
|
+
it('allocates the onTick signal and returns it', () => {
|
|
6
|
+
const clock = createClock();
|
|
7
|
+
const onTick = enableClockSignals(clock);
|
|
8
|
+
expect(clock.onTick).toBe(onTick);
|
|
9
|
+
expect(onTick).not.toBeNull();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('is idempotent — a second call returns the same signal', () => {
|
|
13
|
+
const clock = createClock();
|
|
14
|
+
const first = enableClockSignals(clock);
|
|
15
|
+
const second = enableClockSignals(clock);
|
|
16
|
+
expect(second).toBe(first);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
});
|