Clock

The Clock: the engine's time. Its ticks give the seconds since the frame before, once a frame, which every running animation counts, and now the Environment's time, the same for the rest of a synchronous block. An Environment builds it with layer, over its RefreshFrameSource, so every Environment's Clock runs the same loop: it starts at its first subscription, ticks once a frame, and stops at the first frame that finds no one subscribed.

import * as Clock from "@wardic/core/Clock"

const clock = yield* Clock.Clock
yield* clock.ticks.pipe(Stream.take(3), Stream.runForEach((dt) => Effect.log(dt)))

Classes

Clock

The engine's time: each frame's seconds, and the Environment's time now. A subscription that starts an idle Clock gets its first tick at the next frame, with NOMINAL_DT, and a measured interval from the second frame on. The Clock goes idle only at the first frame that finds no subscriber, so an animation replaced by another in the same task keeps it ticking.

Extends

  • Context.Service

Properties

now
readonly now: () => number;

The Environment's time now, in ms, the same for the rest of a synchronous block, as Motion's sync-time: what a key's velocity is read against, so a test Environment's Clock drives velocities too.

Returns

number

tick
readonly tick: (t) => Effect<void>;

Advances the Clock to time t: what an Environment that drives its own Clock calls.

Parameters
t

number

Returns

Effect<void>

ticks
readonly ticks: Stream<number>;

The seconds since the frame before, one per frame: what animations count.

Variables

fromRefreshFrames

const fromRefreshFrames: <Handle>(source) => Effect.Effect<Context.Service.Shape<typeof Clock>, never, Scope.Scope>;

A Clock driven by source's frames, its loop running in the Scope, and its frame asked for cancelled when the Scope closes. An Environment provides its source as a member and builds its Clock with layer; this is for a source that isn't in the Environment.

Type Parameters

Handle

Handle

Parameters

source

Shape<Handle>

Returns

Effect.Effect<Context.Service.Shape<typeof Clock>, never, Scope.Scope>


layer

const layer: Layer.Layer<Clock, never, RefreshFrameSource>;

The Clock over the Environment's RefreshFrameSource, its loop in the Layer's scope. An Environment provides both from one source, so the Clock and a binding's flush run on the same frames.


NOMINAL_DT

const NOMINAL_DT: number;

The seconds a Clock ticks while it has no measured interval yet, at its first frame: one frame at 60 Hz, as Motion's first frame after its loop wakes.

Functions

syncNow()

function syncNow(read): () => number;

read, read once a synchronous block: the first call reads it and keeps it until the end of the task, so every sink a tick runs, and an animation replaced in the same task, read one time, as Motion's sync-time. A Clock's now for an Environment whose time is a wall clock.

Parameters

read

() => number

Returns

() => number

Example

const now = Clock.syncNow(() => performance.now())