Skip to content
MotionActor
Esc
↑↓navigate↵open⌘Jpreview
On this page

ClockActor

A stopwatch whose elapsed time is computed from the frame, from @motionactor/primitives.

ClockActor counts frames while it runs. It stores only when it started and what it had counted before, and works out the elapsed time from the frame being resolved, so frame 105 reads the same whether playback got there by playing or by seeking.

import { function child<TBlueprint extends ActorClass<object>, TOwner extends object = object>(blueprint: TBlueprint, ...[overrides]: ChildOverridesArg<TBlueprint, TOwner>): ChildField<TBlueprint, TOwner>child, function createScene<TSceneExports, const I extends SceneInputs = Readonly<Record<never, SceneInput>>, const L extends SceneLayers = Readonly<Record<never, SceneLayer<BackendRef<string>>>>>(script: SceneScript<I, L, TSceneExports>, options?: SceneDefinitionOptions<I, L>): SceneDefinition<I, L, TSceneExports>
Declare a scene. Nothing compiles until a host builds it: `scene.build({ viewport, fps, inputs })` runs the script as `(ctx, inputs, viewport, layers)` and returns the compiled scene. `ctx.spawn` places a root actor in the default layer; `layers.<key>.spawn` places it in a declared one. `ctx.stage` stages another scene on this scene's clock, and a staged scene may stage again.
createScene
, function derived<TThis, T>(fn: (this: TThis) => T): DerivedDefinition<T, TThis>derived, class LayoutActor<TEvents extends ActorEventMap = {}>LayoutActor } from "@motionactor/core";
import { class ClockActorClockActor } from "@motionactor/primitives"; class class StopwatchStopwatch extends class LayoutActor<TEvents extends ActorEventMap = {}>LayoutActor { Stopwatch.clock: ChildField<typeof ClockActor, object>clock = child<typeof ClockActor, object>(blueprint: typeof ClockActor, overrides?: ChildOverrides<typeof ClockActor, object> | undefined): ChildField<typeof ClockActor, object>child(class ClockActorClockActor); Stopwatch.label: DerivedDefinition<string, unknown>label = derived<unknown, string>(fn: (this: unknown) => string): DerivedDefinition<string, unknown>derived(() => this.Stopwatch.clock: ChildField<typeof ClockActor, object>clock.
ClockActor.elapsedSeconds: DerivedDefinition
() => number
elapsedSeconds
().Number.toFixed(fractionDigits?: number): string
Returns a string representing a number in fixed-point notation.
@paramfractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
toFixed
(1));
} const
const compiled: CompiledScene<{
    watch: Stopwatch;
}, CompiledLayersOf<Readonly<Record<never, SceneLayer<BackendRef<string>>>>>>
compiled
=
createScene<{
    watch: Stopwatch;
}, Readonly<Record<never, SceneInput>>, Readonly<Record<never, SceneLayer<BackendRef<string>>>>>(script: SceneScript<Readonly<Record<never, SceneInput>>, Readonly<Record<never, SceneLayer<BackendRef<string>>>>, {
    watch: Stopwatch;
}>, options?: SceneDefinitionOptions<Readonly<Record<never, SceneInput>>, Readonly<Record<never, SceneLayer<BackendRef<string>>>>> | undefined): SceneDefinition<...>
Declare a scene. Nothing compiles until a host builds it: `scene.build({ viewport, fps, inputs })` runs the script as `(ctx, inputs, viewport, layers)` and returns the compiled scene. `ctx.spawn` places a root actor in the default layer; `layers.<key>.spawn` places it in a declared one. `ctx.stage` stages another scene on this scene's clock, and a staged scene may stage again.
createScene
(function* (ctx: SceneContextctx) {
const const watch: Stopwatchwatch = ctx: SceneContextctx.
CompileContext.spawn<Stopwatch>(definition: ActorClass<Stopwatch>, overrides?: {
    clock?: {
        accumulatedFrames?: SignalInputValue<number> | undefined;
        startedAtFrame?: SignalInputValue<number> | undefined;
        running?: SignalInputValue<boolean> | undefined;
        elapsedFrames?: undefined;
        elapsedSeconds?: undefined;
        elapsedMilliseconds?: undefined;
    } | undefined;
    id?: undefined;
    cursor?: undefined;
    cursorSeconds?: undefined;
    sceneFps?: undefined;
    onInit?: undefined;
    onEnter?: undefined;
    onExit?: undefined;
    ... 16 more ...;
    bounds?: undefined;
} | undefined, options?: {
    ...;
} | undefined): Stopwatch (+1 overload)
spawn
(class StopwatchStopwatch);
yield* const watch: Stopwatchwatch.Stopwatch.clock: ChildField<typeof ClockActor, object>clock.ClockActor.start(duration?: Duration): Generator<number, void, unknown>
Start counting from the cursor. A running clock keeps its count.
start
(2);
yield* const watch: Stopwatchwatch.Stopwatch.clock: ChildField<typeof ClockActor, object>clock.ClockActor.pause(duration?: Duration): Generator<number, void, unknown>
Stop counting and keep the count.
pause
(1);
yield* const watch: Stopwatchwatch.Stopwatch.clock: ChildField<typeof ClockActor, object>clock.ClockActor.resume(duration?: Duration): Generator<number, void, unknown>
Count on from where the clock paused.
resume
(1);
return { watch: Stopwatchwatch }; }).
SceneDefinition<Readonly<Record<never, SceneInput>>, Readonly<Record<never, SceneLayer<BackendRef<string>>>>, { ...; }>.build(args: SceneBuildInput<Readonly<Record<never, SceneInput>>>): CompiledScene<{
    watch: Stopwatch;
}, CompiledLayersOf<Readonly<Record<never, SceneLayer<BackendRef<string>>>>>>
build
({ viewport: SceneViewportviewport: { SceneViewport.width: numberwidth: 1920, SceneViewport.height: numberheight: 1080 }, fps: numberfps: 30 });
const compiled: CompiledScene<{
    watch: Stopwatch;
}, CompiledLayersOf<Readonly<Record<never, SceneLayer<BackendRef<string>>>>>>
compiled
.
CompiledScene<{ ...; }, CompiledLayersOf<...>>.at(frame: Frame, options?: FrameResolutionOptions): FrameState<{
    watch: Stopwatch;
}>
at
(60).
FrameState<{ ...; }>.scene: {
    watch: ResolvedActorOfInstance<Stopwatch> | undefined;
}
scene
.watch: ResolvedActorOfInstance<Stopwatch> | undefinedwatch?.label: string | undefinedlabel; // "2.0"
const compiled: CompiledScene<{
    watch: Stopwatch;
}, CompiledLayersOf<Readonly<Record<never, SceneLayer<BackendRef<string>>>>>>
compiled
.
CompiledScene<{ ...; }, CompiledLayersOf<...>>.at(frame: Frame, options?: FrameResolutionOptions): FrameState<{
    watch: Stopwatch;
}>
at
(75).
FrameState<{ ...; }>.scene: {
    watch: ResolvedActorOfInstance<Stopwatch> | undefined;
}
scene
.watch: ResolvedActorOfInstance<Stopwatch> | undefinedwatch?.label: string | undefinedlabel; // "2.0", paused
const compiled: CompiledScene<{
    watch: Stopwatch;
}, CompiledLayersOf<Readonly<Record<never, SceneLayer<BackendRef<string>>>>>>
compiled
.
CompiledScene<{ ...; }, CompiledLayersOf<...>>.at(frame: Frame, options?: FrameResolutionOptions): FrameState<{
    watch: Stopwatch;
}>
at
(105).
FrameState<{ ...; }>.scene: {
    watch: ResolvedActorOfInstance<Stopwatch> | undefined;
}
scene
.watch: ResolvedActorOfInstance<Stopwatch> | undefinedwatch?.label: string | undefinedlabel; // "2.5"

Commands

Each command changes the clock at the cursor and then waits its duration in seconds, 0 by default. start(2) reads as “start, and let it run for two seconds”.

Command Does
start(duration?) Starts counting. On a running clock it does nothing
pause(duration?) Stops counting and keeps the count
resume(duration?) Counts on from the kept count. The same as start
reset(duration?) Stops the clock and zeroes it

Values

Field
elapsedFrames Frames counted
elapsedSeconds elapsedFrames over the build’s frame rate
elapsedMilliseconds The same, in milliseconds
running Whether it is counting

The elapsed values are derived, so another actor’s derived value or a renderer can read them like any signal. A countdown is total - clock.elapsedSeconds().

Past the scene’s last frame a running clock reads as it did on that frame, because every later frame resolves as the last one. It never reads wall-clock time.

ClockActor measures time and runs nothing. To repeat work, use runtime.loop. To wait, use ctx.wait.

Was this page helpful?