# `tecs.sequence` Snapshot-safe programs, waits, ownership, actions, and tween timelines. Sequences store control flow as data. A snapshot, a rewind, or a reload can therefore preserve a playback's program, instruction pointer, waits, bindings, and parameters. A coroutine cannot be serialized, so the sequencer compiles authored steps into instructions and stores each playback's cursor, wait, and branch as ordinary data. `nupp.tasks` owns the world's logical update; it cannot own a playback that has to survive a save file. ## Programs and actions Register an action on the world, name it from a program, and bind each playback to the entities it acts on: ```nupp tecs.sequence.registerAction(world, "game.lockControls", function(_world, _context): nil controlsLocked = true end) local intro = tecs.sequence.define("game.bossIntro", { tecs.sequence.call("game.lockControls"), tecs.sequence.wait(1.5), tecs.sequence.emit("boss.ready"), }) local playback = tecs.sequence.play(world, intro, {owner = encounter, bindings = {boss = bossEntity}}) ``` Program names are a snapshot compatibility surface. Use stable qualified names. Redefining a name publishes a new version: running playbacks keep the version they started on, and later `play` calls use the new one. Action bodies resolve by name when they run, so a reload can replace action code without moving a live instruction pointer. Actions run synchronously and cannot suspend. An action that raises faults its playback after preserving the mutations it already completed. ## Clocks and waits `"fixed"` advances once per fixed step and serves deterministic gameplay. `"frame"` advances once per gameplay frame and serves scripted input, which needs exactly one decision per frame however many fixed steps that frame runs. `"presentation"` advances once per frame carrying the frame's real elapsed time, and serves values the simulation never reads. Durations are seconds. Step and tick values count whole advances of the program's clock. Every positive duration waits at least one tick, and `waitSteps(0)` yields until the next tick and gives a loop a fresh instruction budget. `ecs.newWorld({nominalFrameTime = seconds})`, or `Application.Config.world`, sets the duration used to convert frame and presentation waits to ticks. It is positive and finite and defaults to 1/60 in both windowed and headless sessions. `setNominalFrameTime(world, seconds)` changes future conversions in that world only; already scheduled tick deadlines do not move. Restore a saved playback into a world configured for its intended cadence. `sourceKey(key, component, fields)` resolves a moving tween destination through `World.byKey` on each evaluation, including after snapshot load or a new entity claims the key. `TrackingTarget.key` does the same when its `entity` is zero. An explicit entity id takes precedence and a stale id does not fall back to the key. A missing source contributes zero, as other missing tracking sources do. ## Ownership `owner` ties a playback to an entity, and despawning that entity cancels the playback. A named `channel` gives one owner a replaceable slot, so starting a second playback on the same channel cancels the first. Pause uses named holders, and a playback resumes only after every holder releases it. A branch inherits owner, bindings, parameters, budget, and pause state, and cannot outlive its parent. Each playback receives a bounded instruction budget per tick and faults with `budgetExceeded` rather than hanging the frame. ## Timelines A timeline compiles tweens into the same runtime and keeps the same ownership, clock, channel, pause, and snapshot rules. Targets interpolate component fields. A parallel block shares a start time, and a sequential block starts after the one before it ends. ## Program construction A sequence is written by calling the node constructors. The API has no generic row decoder or shared data schema. A game that stores sequences as data decodes its own schema into these constructors. ## Types ### `Action` _type_ ```nupp type Action = function(exclusive world: entityworld.World, ctx: ActionContext): nil ``` Defines a registered effect that runs synchronously and cannot suspend. ### `ActionContext` _record_ ```nupp record ActionContext handle: Handle owner: integer args: {any} params: {[string]: any}? cursor: Cursor? entity: function(borrows self: ActionContext, borrows world: entityworld.World, name: string): integer? bind: function(exclusive self: ActionContext, name: string, entity: integer?): nil end ``` Provides the context a registered action receives. #### Methods ##### `entity` ```nupp entity: function(borrows self: ActionContext, borrows world: entityworld.World, name: string): integer? ``` Resolves a named binding to a live entity. The world is a parameter rather than a field of this record, because the sequencer reuses one context across calls and may not keep a view of the world the running tick borrows. An action already has the world it ran under. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `borrows self` | `ActionContext` | the context the running action received | | `borrows world` | `entityworld.World` | the world the running action received | | `name` | `string` | the binding name supplied through `PlayOptions.bindings` | ###### Returns | Type | Description | | --- | --- | | `integer?` | the entity id, or nil when the binding is missing or its entity is no longer alive | ##### `bind` ```nupp bind: function(exclusive self: ActionContext, name: string, entity: integer?): nil ``` Names an entity for the steps that follow, so an action that creates one can hand it on. Bindings travel with the playback and survive a snapshot. Passing nil forgets the name. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `ActionContext` | the context the running action received | | `name` | `string` | the binding name later steps resolve | | `entity` | `integer?` | the entity id to bind, or nil to forget the name | ###### Returns | Type | Description | | --- | --- | | `nil` | | #### Fields ##### `handle` ```nupp handle: Handle ``` Read-only. Identifies the playback, for `status` or `cancel` from inside an action. ##### `owner` ```nupp owner: integer ``` Read-only. Reports the `owner` supplied at `play`, or zero. ##### `args` ```nupp args: {any} ``` Read-only. Carries the `call` node's constants with every entity reference already resolved to an entity id. ##### `params` ```nupp params: {[string]: any}? ``` Read-only. Carries the `params` supplied at `play`, or nil. ##### `cursor` ```nupp cursor: Cursor? ``` Engine-owned. Points at the running cursor. Game code uses `entity` and `bind` instead of reading this. ### `Awaitable` _record_ ```nupp record Awaitable isPending: function(borrows world: entityworld.World, entity: integer, key: string?): boolean setPaused: (function(exclusive world: entityworld.World, entity: integer, key: string?, paused: boolean): nil)? end ``` Defines the response an `await` step's provider must give. #### Methods ##### `isPending` ```nupp isPending: function(borrows world: entityworld.World, entity: integer, key: string?): boolean ``` Caller-writable. Reports whether the work named by `entity` and `key` is still going. The sequencer calls this at a fixed-step boundary for every cursor parked on the name, so it must be cheap and must not mutate the world. Reporting false for work that never started is correct: a program waiting on an animation that is already over should carry on rather than hang. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `borrows world` | `entityworld.World` | | | `entity` | `integer` | | | `key` | `string?` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | #### Fields ##### `setPaused` ```nupp setPaused: (function(exclusive world: entityworld.World, entity: integer, key: string?, paused: boolean): nil)? ``` Caller-writable. Stops and starts the work when the provider knows how, so pausing a cutscene stops the animation it waits on. Optional. ### `ClockId` _type_ ```nupp type ClockId = "fixed" | "frame" | "presentation" ``` Selects the clock a program runs against. ### `DefineOptions` _type_ ```nupp type DefineOptions = {clock: ClockId?} ``` Configures `define`. ### `EasingFunction` _type_ ```nupp type EasingFunction = function(t: number): number ``` Maps normalized input progress to eased output progress. ### `EasingName` _type_ ```nupp type EasingName = "linear" | "quadIn" | "quadOut" | "quadInOut" | "quadOutIn" | "cubicIn" | "cubicOut" | "cubicInOut" | "cubicOutIn" | "quartIn" | "quartOut" | "quartInOut" | "quartOutIn" | "quintIn" | "quintOut" | "quintInOut" | "quintOutIn" | "sineIn" | "sineOut" | "sineInOut" | "sineOutIn" | "expoIn" | "expoOut" | "expoInOut" | "expoOutIn" | "backIn" | "backOut" | "backInOut" | "backOutIn" | "elasticIn" | "elasticOut" | "elasticInOut" | "elasticOutIn" | "bounceIn" | "bounceOut" | "bounceInOut" | "bounceOutIn" ``` Names a built-in easing curve. ### `Emission` _record_ ```nupp record Emission name: string args: {any} handle: Handle end ``` `@derive(events.Event)` `@event(name="SequenceEmission")` The payload an `emit` step delivers at address zero. #### Fields ##### `name` ```nupp name: string ``` Read-only. Carries the name supplied to `sequence.emit`. ##### `args` ```nupp args: {any} ``` Read-only. Carries the emitted constants with bindings resolved. This list is built per emission and is the observer's to keep. ##### `handle` ```nupp handle: Handle ``` Read-only. Identifies the playback that emitted it. ### `EntityRef` _record_ ```nupp record EntityRef bindName: string isBinding: boolean end ``` References an entity supplied at `play` time. #### Fields ##### `bindName` ```nupp bindName: string ``` Read-only. Names the binding this reference resolves. ##### `isBinding` ```nupp isBinding: boolean ``` Read-only. Marks this table apart from an ordinary table argument. ### `Evaluator` _record_ ```nupp record Evaluator resolve: (function(data: any): any)? newState: (function(program: Program, data: any, cursor: Cursor): any)? step: function(exclusive world: entityworld.World, cursor: Cursor, dt: number): boolean save: (function(state: any): any)? load: (function(program: Program, data: any, saved: any): any)? end ``` Defines the evaluator an `eval` step runs every tick. #### Methods ##### `step` ```nupp step: function(exclusive world: entityworld.World, cursor: Cursor, dt: number): boolean ``` Caller-writable. Advances one cursor by `dt` and returns true once the cursor should move on to the next instruction. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `entityworld.World` | | | `cursor` | `Cursor` | | | `dt` | `number` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | #### Fields ##### `resolve` ```nupp resolve: (function(data: any): any)? ``` Caller-writable. Turns the constant an `eval` step carries into the form that is cheapest to read every tick. Runs once per program constant and the result is shared by every playback of it. ##### `newState` ```nupp newState: (function(program: Program, data: any, cursor: Cursor): any)? ``` Caller-writable. Builds per-cursor working state, or nil when the evaluator needs none. ##### `save` ```nupp save: (function(state: any): any)? ``` Caller-writable. Turns working state into something a snapshot can carry. Without both `save` and `load` an evaluating playback comes back at the start of its state rather than where it was. ##### `load` ```nupp load: (function(program: Program, data: any, saved: any): any)? ``` Caller-writable. Rebuilds working state from what `save` produced. ### `FaultReason` _type_ ```nupp type FaultReason = "unregisteredAction" | "actionError" | "budgetExceeded" | "branchFaulted" | "unregisteredQuery" | "unregisteredEvaluator" | "unregisteredAwaitable" | "unregisteredTween" ``` Explains why a cursor stopped running. ### `Handle` _type_ ```nupp type Handle = integer ``` Identifies one playback through a generation-checked reference that remains meaningful across a snapshot load. ### `Node` _record_ ```nupp record Node kind: string text: string? number: number? count: integer? args: any nodes: {Node}? blocks: {{Node}}? end ``` Represents one authored step produced by a node constructor. #### Fields ##### `kind` ```nupp kind: string ``` Read-only. Names the step this node compiles to. ##### `text` ```nupp text: string? ``` Read-only. Carries the step's name argument, when it takes one. ##### `number` ```nupp number: number? ``` Read-only. Carries the step's numeric argument, when it takes one. ##### `count` ```nupp count: integer? ``` Read-only. Carries the step's integer argument, when it takes one. ##### `args` ```nupp args: any ``` Read-only. Carries the step's constant, when it takes one. Most steps carry a list; an evaluating step carries whatever its evaluator reads. ##### `nodes` ```nupp nodes: {Node}? ``` Read-only. Carries the step's nested block, when it takes one. ##### `blocks` ```nupp blocks: {{Node}}? ``` Read-only. Carries one block per branch for a `parallel` step. ### `PlaybackMode` _type_ ```nupp type PlaybackMode = "once" | "loop" | "pingPong" ``` Selects how a timeline repeats. ### `PlaybackState` _type_ ```nupp type PlaybackState = "running" | "paused" | "completed" | "canceled" | "faulted" ``` Describes the lifecycle state of one playback. ### `PlayOptions` _type_ ```nupp type PlayOptions = { owner: integer?, bindings: {[string]: integer}?, params: {[string]: any}?, budget: integer?, channel: string? } ``` Configures `play`. ### `Program` _record_ ```nupp record Program name: string version: integer clock: ClockId code: {integer} consts: {any} loopCounts: {[integer]: integer} bindingArgs: {[integer]: boolean} evalResolved: {[integer]: any}? end ``` Represents a compiled, immutable program shared by every playback of it. #### Fields ##### `name` ```nupp name: string ``` Read-only. Reports the name passed to `define`. ##### `version` ```nupp version: integer ``` Read-only. Reports the monotonic version, starting at one. ##### `clock` ```nupp clock: ClockId ``` Read-only. Reports the clock this program's waits count. ##### `code` ```nupp code: {integer} ``` Engine-owned. Holds the flat instruction array. Game code reads it through `disassemble` rather than directly. ##### `consts` ```nupp consts: {any} ``` Engine-owned. Holds the constant pool the instructions index. ##### `loopCounts` ```nupp loopCounts: {[integer]: integer} ``` Engine-owned. Maps a jump's address to the iteration count it seeds. ##### `bindingArgs` ```nupp bindingArgs: {[integer]: boolean} ``` Engine-owned. Marks the constant indexes whose argument list holds an entity reference, so a call with plain constants copies nothing. ##### `evalResolved` ```nupp evalResolved: {[integer]: any}? ``` Engine-owned. Caches one resolved constant per evaluating instruction. ### `QueryCondition` _type_ ```nupp type QueryCondition = "any" | "empty" ``` Describes the condition awaited by a `waitQuery` step. ### `RunOptions` _type_ ```nupp type RunOptions = { mode: PlaybackMode?, count: integer? } ``` Configures a nested `tweenRun` operation. ### `Status` _record_ ```nupp record Status state: PlaybackState program: string version: integer pc: integer wakeAt: integer? waitingFor: string? waitingQuery: string? waitingCondition: QueryCondition? waitingAwaitable: string? waitingAwaitableEntity: integer? waitingTween: Handle? tweenOutcome: TweenOutcome? branches: integer joining: boolean fault: FaultReason? faultMessage: string? end ``` Reports a playback's current state. #### Fields ##### `state` ```nupp state: PlaybackState ``` Read-only. Reports the lifecycle state. ##### `program` ```nupp program: string ``` Read-only. Names the program this playback runs. ##### `version` ```nupp version: integer ``` Read-only. Reports the program version this playback runs. ##### `pc` ```nupp pc: integer ``` Read-only. Reports the instruction index. ##### `wakeAt` ```nupp wakeAt: integer? ``` Read-only. Reports the tick this playback next runs on, or nil when it is blocked on something other than a time. ##### `waitingFor` ```nupp waitingFor: string? ``` Read-only. Names the signal this playback is blocked on. ##### `waitingQuery` ```nupp waitingQuery: string? ``` Read-only. Names the query this playback is blocked on. ##### `waitingCondition` ```nupp waitingCondition: QueryCondition? ``` Read-only. Reports the query condition this playback waits for. ##### `waitingAwaitable` ```nupp waitingAwaitable: string? ``` Read-only. Names the awaitable provider this playback is blocked on. ##### `waitingAwaitableEntity` ```nupp waitingAwaitableEntity: integer? ``` Read-only. Names the entity this playback's awaitable is asked about. ##### `waitingTween` ```nupp waitingTween: Handle? ``` Read-only. Identifies the playback this one is blocked on. ##### `tweenOutcome` ```nupp tweenOutcome: TweenOutcome? ``` Read-only. Reports how the last awaited playback ended. ##### `branches` ```nupp branches: integer ``` Read-only. Counts live branches this playback forked and has not joined. ##### `joining` ```nupp joining: boolean ``` Read-only. Reports whether this playback waits at a `join`. ##### `fault` ```nupp fault: FaultReason? ``` Read-only. Explains a faulted playback. ##### `faultMessage` ```nupp faultMessage: string? ``` Read-only. Reports the message accompanying a fault. ### `Step` _record_ ```nupp record Step ticks: integer kind: string name: string args: {any} end ``` Describes one step a playback reaches without branching. #### Fields ##### `ticks` ```nupp ticks: integer ``` Read-only. Counts ticks of the program's clock from the reference point until this step runs. ##### `kind` ```nupp kind: string ``` Read-only. Holds `"call"` or `"emit"`. ##### `name` ```nupp name: string ``` Read-only. Names the action for a call or the event for an emit. ##### `args` ```nupp args: {any} ``` Read-only. Carries the step's constants, unresolved. This list is the program's own rather than a copy, so read it and do not write to it. ### `Target` _record_ ```nupp record Target id: string componentName: string component: components.Component? fields: {string} mode: TargetMode end ``` Describes the component and one to four numeric fields a timeline operation writes. #### Fields ##### `id` ```nupp id: string ``` Read-only. Identifies this target in a compiled slot. A built-in carries its `TargetName`; one built from a component carries the component name joined to its fields. ##### `componentName` ```nupp componentName: string ``` Read-only. Names the component whose fields move. ##### `component` ```nupp component: components.Component? ``` Engine-owned. Caches the resolved component, which a target restored from a snapshot looks up on first use. ##### `fields` ```nupp fields: {string} ``` Read-only. Names the fields written, in the order the destinations line up with them. ##### `mode` ```nupp mode: TargetMode ``` Read-only. Selects how the destinations are interpreted. ### `TargetName` _type_ ```nupp type TargetName = "transform.x" | "transform.y" | "transform.xy" | "transform.rotation" | "transform.rotationShortest" | "transform.scaleX" | "transform.scaleY" | "transform.scaleXY" | "color.a" | "color.rgba" ``` Names a built-in component-field target. ### `TimelineNode` _record_ ```nupp record TimelineNode kind: OperationKind duration: number? easingName: EasingName? target: Target? source: TrackSource? t1: number? t2: number? t3: number? t4: number? name: string? nested: {TimelineNode}? mode: PlaybackMode? count: integer? branches: {{TimelineNode}}? end ``` Represents one authored timeline operation. #### Fields ##### `kind` ```nupp kind: OperationKind ``` Read-only. Names the operation. ##### `duration` ```nupp duration: number? ``` Read-only. Reports the seconds this operation occupies. ##### `easingName` ```nupp easingName: EasingName? ``` Read-only. Names the curve an interpolation follows. ##### `target` ```nupp target: Target? ``` Read-only. Selects the component fields an interpolation writes. ##### `source` ```nupp source: TrackSource? ``` Read-only. Selects where a tracking interpolation reads its destination. ##### `t1` ```nupp t1: number? ``` Read-only. Carries the destination for the target's first field. ##### `t2` ```nupp t2: number? ``` Read-only. Carries the destination for the second field. ##### `t3` ```nupp t3: number? ``` Read-only. Carries the destination for the third field. ##### `t4` ```nupp t4: number? ``` Read-only. Carries the destination for the fourth field. ##### `name` ```nupp name: string? ``` Read-only. Names the event an `emit` operation fires. ##### `nested` ```nupp nested: {TimelineNode}? ``` Read-only. Carries the nested spec a `run` operation plays. ##### `mode` ```nupp mode: PlaybackMode? ``` Read-only. Selects how a `run` operation repeats. ##### `count` ```nupp count: integer? ``` Read-only. Counts the passes a repeating `run` operation makes. ##### `branches` ```nupp branches: {{TimelineNode}}? ``` Read-only. Carries one block per concurrent branch of a `parallel` operation. ### `TimelineOptions` _type_ ```nupp type TimelineOptions = {clock: ClockId?} ``` Configures `timeline`. ### `TrackingTarget` _record_ ```nupp record TrackingTarget entity: integer key: string end ``` Selects a dynamic tracking-source entity. #### Fields ##### `entity` ```nupp entity: integer ``` Caller-writable. Names the source entity directly, or zero for none. ##### `key` ```nupp key: string ``` Caller-writable. Names the source entity by world key when `entity` is zero. Resolution follows the current live claimant on every evaluation. This persisted field name is a compatibility surface. ### `TrackSource` _record_ ```nupp record TrackSource kind: TrackSourceKind key: string? relationshipName: string? relationship: components.Component? componentName: string component: components.Component? fields: {string} end ``` Provides a live component-field tracking source. #### Fields ##### `kind` ```nupp kind: TrackSourceKind ``` Read-only. Selects which entity the source reads from. ##### `key` ```nupp key: string? ``` Read-only. Names the world key a keyed source resolves on every evaluation. ##### `relationshipName` ```nupp relationshipName: string? ``` Read-only. Names the relationship traversed by a `related` source. ##### `relationship` ```nupp relationship: components.Component? ``` Engine-owned. Caches the resolved relationship component. ##### `componentName` ```nupp componentName: string ``` Read-only. Names the component the source reads. ##### `component` ```nupp component: components.Component? ``` Engine-owned. Caches the resolved component. ##### `fields` ```nupp fields: {string} ``` Read-only. Names the fields read, lined up with the target's own. ### `TweenOutcome` _type_ ```nupp type TweenOutcome = "completed" | "canceled" | "replaced" | "targetLost" ``` Reports how the playback awaited by `waitTween` ended. ## Functions ### `activeCount` _function_ ```nupp function activeCount(exclusive world: ecs.World): integer ``` Returns the number of live playbacks, for tests and diagnostics. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the playbacks | #### Returns | Type | Description | | --- | --- | | `integer` | the count, with branches and `playTween`-started playbacks counted individually | ### `await` _function_ ```nupp function await(provider: string, target: EntityRef, key: string?): Node ``` Builds a step that waits for work outside the sequencer to finish. A subsystem registers a provider under a name and answers whether the work is still going; this parks the playback until it is not. The sequencer never learns what the work is, which is how a program waits on a sprite animation without the sequencer requiring the renderer. A binding that is missing or dead is not a fault, and neither is a provider reporting work that never started. #### Arguments | Name | Type | Description | | --- | --- | --- | | `provider` | `string` | the registered provider name, checked before the binding; an unregistered name faults the playback with `unregisteredAwaitable` | | `target` | `EntityRef` | a `bind` reference and nothing else | | `key` | `string?` | handed to the provider unread, for a provider that answers about more than one thing per entity | #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | #### Raises - when the provider name is empty or the target is not a `bind` reference ### `bind` _function_ ```nupp function bind(name: string): EntityRef ``` References an entity supplied through `PlayOptions.bindings`. The reference resolves when the instruction using it runs rather than at `play`, so a binding may name an entity that does not exist yet. A missing binding resolves to nothing instead of faulting. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | the binding name, which must not be empty | #### Returns | Type | Description | | --- | --- | | `EntityRef` | a reference to put in a `call` or `emit` argument list, or to hand to `playTween` or `await` | #### Raises - when the name is empty ### `call` _function_ ```nupp function call(action: string, ...: any): Node ``` Builds a step that runs a registered action. The action name resolves per world when the instruction runs, so a program may name an action registered later. A name still unregistered when the step runs faults the playback with `unregisteredAction`. The step costs no tick. #### Arguments | Name | Type | Description | | --- | --- | --- | | `action` | `string` | the registered action name | | `...` | `any` | the constants the action receives, which are the same values for every playback of this program; put anything that differs between two playbacks in `PlayOptions.params` instead | #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | #### Raises - when the action name is empty ### `cancel` _function_ ```nupp function cancel(exclusive world: ecs.World, handle: Handle): boolean ``` Stops a playback and releases its cursor. This is safe on a finished handle. Cancelling takes the branches the playback forked with it, and a playback parked in a `waitTween` on the one canceled is told `canceled` and resumes. What a `playTween` started is a playback in its own right and is not canceled with the one that started it, unlike a pause, which cascades to it; stop it through its owner with `cancelOwnedBy`. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the playback | | `handle` | `Handle` | the playback to stop, read against this world's cursor arena | #### Returns | Type | Description | | --- | --- | | `boolean` | false when the handle names nothing running, whether it already finished or was already canceled | ### `cancelOwnedBy` _function_ ```nupp function cancelOwnedBy(exclusive world: ecs.World, owner: integer, reason: TweenOutcome?): integer ``` Cancels every playback owned by an entity. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the playbacks | | `owner` | `integer` | an entity id; nothing owns a playback started without an owner, so no argument reaches one and only `cancel` on its handle stops it | | `reason` | `TweenOutcome?` | what a playback parked in a `waitTween` on one of these is told, defaulting to `canceled` | #### Returns | Type | Description | | --- | --- | | `integer` | the number of canceled playbacks, counting each cursor once and reaching branches through their inherited owner | ### `currentStep` _function_ ```nupp function currentStep(exclusive world: ecs.World, clock: ClockId?): integer ``` Returns a clock's current tick as counted by the sequencer. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the clock counters | | `clock` | `ClockId?` | which of the three counters to read, defaulting to `"fixed"` | #### Returns | Type | Description | | --- | --- | | `integer` | the ticks of that one clock, counted from when this world's sequencer state was created and comparable only against another reading of the same clock | ### `define` _function_ ```nupp function define(name: string, nodes: {Node}, options: DefineOptions?): Program ``` Compiles a program under a stable symbolic name. Defining over a name already in use publishes a new version rather than replacing the old one: playbacks already running keep the version they started on, and only later `play` calls see the new one. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | the stable symbolic name, which is a snapshot compatibility surface | | `nodes` | `{Node}` | the authored steps, which may be empty, in which case the program completes on its first tick | | `options` | `DefineOptions?` | the clock the program's waits count, defaulting to `"fixed"` | #### Returns | Type | Description | | --- | --- | | `Program` | the compiled program, immutable and shared by every playback of it, so the same value plays on any number of worlds | #### Raises - when the name is empty, the clock is not one of the three names, or an entry is not a step ### `disassemble` _function_ ```nupp function disassemble(value: Program, pc: integer?): string ``` Renders a program as readable instructions. #### Arguments | Name | Type | Description | | --- | --- | --- | | `value` | `Program` | a program from `define` or `timeline` | | `pc` | `integer?` | the instruction to mark, as a playback's `status` reports it, or nil for an unmarked listing | #### Returns | Type | Description | | --- | --- | | `string` | a header naming the program and its version, then one line per instruction, newline separated, for reading rather than for parsing | ### `easing` _function_ ```nupp function easing(name: EasingName): EasingFunction? ``` Returns a built-in easing curve by name. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `EasingName` | the curve name | #### Returns | Type | Description | | --- | --- | | `EasingFunction?` | the curve, or nil when the name names no built-in | ### `emit` _function_ ```nupp function emit(event: string, ...: any): Node ``` Builds a step that emits a sequence event at address zero. The step occupies no tick, so the step after it runs in the same one. Each emission copies its argument list and sends it with the event, so an observer may keep it, unlike the list an action receives. #### Arguments | Name | Type | Description | | --- | --- | --- | | `event` | `string` | the name carried on the emission | | `...` | `any` | the constants delivered on the emission with every entity reference already resolved | #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | #### Raises - when the event name is empty ### `eval` _function_ ```nupp function eval(evaluator: string, data: any): Node ``` Builds a step that evaluates a registered evaluator every tick until it finishes. Unlike every other step this one does not hand the tick back: the playback joins its clock's active set and the runtime steps it each tick. Values that move every frame need this behavior. #### Arguments | Name | Type | Description | | --- | --- | --- | | `evaluator` | `string` | the registered evaluator name, resolved when the instruction runs; an unregistered name faults the playback with `unregisteredEvaluator` | | `data` | `any` | the constant the evaluator receives, passed through its `resolve` once per program constant and shared by every playback, so it must remain plain data and the evaluator must not write per-playback state into it | #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | #### Raises - when the evaluator name is empty ### `fork` _function_ ```nupp function fork(nodes: {Node}): Node ``` Builds a step that starts a branch alongside the rest of the program. The branch is a playback of its own running the same program at a different instruction, inheriting the owner, bindings, parameters, and instruction budget of the playback that forked it. It starts once that playback next waits, joins, or ends, within the same tick. A branch never outlives its parent, and a branch that faults takes its parent with it, faulted `branchFaulted`, rather than leaving a join one branch short forever. #### Arguments | Name | Type | Description | | --- | --- | --- | | `nodes` | `{Node}` | the branch body, which must not be empty and which reads and writes the forking playback's own bindings table rather than a copy | #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | #### Raises - when the block is empty ### `hasAction` _function_ ```nupp function hasAction(exclusive world: ecs.World, name: string): boolean ``` Reports whether a world has registered an action name. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the action registry | | `name` | `string` | the action name to find | #### Returns | Type | Description | | --- | --- | | `boolean` | false for a name this world never registered, including one another world has | ### `hasQuery` _function_ ```nupp function hasQuery(exclusive world: ecs.World, name: string): boolean ``` Reports whether a world has registered a query name. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the query registry | | `name` | `string` | the query name to find | #### Returns | Type | Description | | --- | --- | | `boolean` | false for a name this world never registered | ### `join` _function_ ```nupp function join(): Node ``` Builds a step that waits for every branch not yet joined. It falls straight through when there are none, and when the last branch finishes the waiting playback resumes within that same tick. #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | ### `loop` _function_ ```nupp function loop(count: integer?, nodes: {Node}): Node ``` Builds a step that repeats a block. #### Arguments | Name | Type | Description | | --- | --- | --- | | `count` | `integer?` | the iterations, or nil to repeat until canceled | | `nodes` | `{Node}` | the block, which must not be empty and which is run in order and started again from its first node | #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | #### Raises - when the count is not a positive whole number, or the block is empty ### `parallel` _function_ ```nupp function parallel(blocks: {{Node}}): Node ``` Builds a step that forks several blocks and waits for all of them. This is a `fork` per block followed by one `join`. Blocks start in argument order, and each shares the playback's bindings table as a `fork` does. #### Arguments | Name | Type | Description | | --- | --- | --- | | `blocks` | `{{Node}}` | one non-empty block per branch | #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | #### Raises - when no block is supplied or one of them is empty ### `pause` _function_ ```nupp function pause(exclusive world: ecs.World, handle: Handle, holder: string?): boolean ``` Suspends a playback, its branches, and anything it started. Pause is holder counted: two systems can hold the same playback for unrelated reasons, and it runs again only when the last one lets go, so whichever resumes first cannot undo the other. Its wait, if any, resumes from where it paused, and what it is waiting on stops with it when the awaitable provider knows how. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the playback | | `handle` | `Handle` | the playback to pause | | `holder` | `string?` | any string, treated as a set rather than a count, so two pauses under the same holder are one hold; it defaults to `"user"` | #### Returns | Type | Description | | --- | --- | | `boolean` | whether the playback stopped, which is false when another holder already had it or the handle names nothing running | ### `play` _function_ ```nupp function play(exclusive world: ecs.World, value: Program, options: PlayOptions?): Handle ``` Starts a program. The first instruction runs on the next tick of the program's own clock, never inside this call. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the new playback | | `value` | `Program` | a program from `define` or `timeline`, not a name; the playback runs this version for its whole life | | `options` | `PlayOptions?` | the owner, bindings, parameters, budget, and channel; taking a channel another playback on the same owner holds cancels that one first, reporting `replaced` to anything waiting on it | #### Returns | Type | Description | | --- | --- | | `Handle` | a handle to the new playback, carrying a generation so one whose playback has ended never names a later playback that took the same slot | ### `playbacks` _function_ ```nupp function playbacks(exclusive world: ecs.World): {Handle} ``` Returns handles for every live playback in a stable order. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the playbacks | #### Returns | Type | Description | | --- | --- | | `{Handle}` | a caller-owned table ordered by cursor slot, which is stable within a run but differs from creation order because new playbacks reuse free slots | ### `playTween` _function_ ```nupp function playTween(timeline: string, target: EntityRef, params: {[string]: any}?): Node ``` Builds a step that plays a registered timeline on a bound entity. The step costs no tick. It starts a separate playback owned by the bound entity, running on the named program's clock and using this playback's instruction budget. A binding that is missing or dead is not a fault: nothing plays, and a following `waitTween` resumes at once reporting `targetLost`. #### Arguments | Name | Type | Description | | --- | --- | --- | | `timeline` | `string` | the timeline name, resolved when the instruction runs and always to the newest version; an undefined name faults the playback with `unregisteredTween` | | `target` | `EntityRef` | a `bind` reference and nothing else | | `params` | `{\[string\]: any}?` | the started playback's parameters, so `mode`, `count`, `speed`, `delay` and `channel` shape it as they do for `play` | #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | #### Raises - when the timeline name is empty or the target is not a `bind` reference ### `plugin` _function_ ```nupp function plugin(exclusive world: ecs.World): nil ``` Installs the sequencer into a world. Installing twice on the same world does nothing, so a world that scripts input may install the sequencer itself rather than relying on the application having done it. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world receiving sequencer state, systems, and the snapshot handler | #### Returns | Type | Description | | --- | --- | | `nil` | | ### `program` _function_ ```nupp function program(name: string, version: integer?): Program? ``` Returns the newest version of a defined program, or a requested version. Every version a playback still runs stays reachable, and the newest version of a name is never dropped. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | a name previously passed to `define` or `timeline` | | `version` | `integer?` | the version to look up, starting at one, or nil for the newest | #### Returns | Type | Description | | --- | --- | | `Program?` | the program, or nil when the name was never defined or that version has been dropped | ### `programNames` _function_ ```nupp function programNames(): {string} ``` Returns the names of every defined program, sorted. #### Returns | Type | Description | | --- | --- | | `{string}` | a caller-owned list; registration is process-wide, so this spans every world in the process | ### `registerAction` _function_ ```nupp function registerAction(exclusive world: ecs.World, name: string, action: Action): nil ``` Registers an action a `call` step can name. Actions must obey the deterministic-action contract to keep replay and rewind meaningful: no wall-clock reads, no file or network access, and randomness only from a generator whose state travels with the snapshot. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the action registry | | `name` | `string` | the action name, which is per world unlike an evaluator or an awaitable; registering it twice replaces the action, and a playback resolves the name at each `call`, so one already running picks the new one up | | `action` | `Action` | the body, which faults its playback with `actionError` when it raises, leaving whatever it already wrote to the world written | #### Returns | Type | Description | | --- | --- | | `nil` | | #### Raises - when the name is empty ### `registerAwaitable` _function_ ```nupp function registerAwaitable(name: string, provider: Awaitable): nil ``` Registers a provider an `await` step can name. Registration is process-wide, like an evaluator, because a provider is code. Registering a name twice replaces the provider, so a playback already parked on the name asks the new one at the next fixed step. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | the provider name | | `provider` | `Awaitable` | the provider, which must carry `isPending`; without `setPaused` it leaves its work running when a pause stops the waiting playback | #### Returns | Type | Description | | --- | --- | | `nil` | | #### Raises - when the name is empty or the provider has no `isPending` ### `registerEvaluator` _function_ ```nupp function registerEvaluator(name: string, evaluator: Evaluator): nil ``` Registers an evaluator an `eval` step can name. Registration is process-wide, like a program: an evaluator is code, and two worlds evaluating the same name run the same thing. Registering a name twice replaces it. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | the evaluator name | | `evaluator` | `Evaluator` | the evaluator, which must carry `step`; without `save` and `load` a playback evaluating this name comes back from a snapshot at the start of its state rather than where it was | #### Returns | Type | Description | | --- | --- | | `nil` | | #### Raises - when the name is empty or the evaluator has no `step` ### `registerQuery` _function_ ```nupp function registerQuery(exclusive world: ecs.World, name: string, descriptor: ecs.QueryDescriptor): nil ``` Registers a query a `waitQuery` step can name. Registering a name again re-tests every playback already parked on it, against the new query, at the next fixed step. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the query registry | | `name` | `string` | the query name | | `descriptor` | `ecs.QueryDescriptor` | the include and exclude constraints | #### Returns | Type | Description | | --- | --- | | `nil` | | #### Raises - when the name is empty ### `resume` _function_ ```nupp function resume(exclusive world: ecs.World, handle: Handle, holder: string?): boolean ``` Releases one holder's claim on a paused playback. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the playback | | `handle` | `Handle` | the paused playback | | `holder` | `string?` | the string that took the hold, defaulting to `"user"`; releasing one that never held it changes nothing | #### Returns | Type | Description | | --- | --- | | `boolean` | whether the playback started running again, which is true only for the last holder to let go; a wake time that passed while it was held runs it on the next tick rather than immediately | ### `setInstructionBudget` _function_ ```nupp function setInstructionBudget(exclusive world: ecs.World, instructions: integer): nil ``` Sets the per-tick instruction budget for playbacks that ask for none. The budget caps how many instructions one playback runs per tick, and exceeding it faults the playback with `budgetExceeded` rather than deferring the rest, so it guards against a loop with no wait in it rather than acting as a scheduler. It applies to playbacks started after this call. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world the budget applies to | | `instructions` | `integer` | the budget, which must be at least one | #### Returns | Type | Description | | --- | --- | | `nil` | | #### Raises - when the budget is less than one ### `setNominalFrameTime` _function_ ```nupp function setNominalFrameTime(exclusive world: ecs.World, seconds: number): nil ``` Sets the nominal frame duration a `frame` or `presentation` wait converts seconds against. The nominal duration is used rather than a frame's measured time because a wake is a tick number fixed when the wait runs and never revisited. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world whose future waits use this duration. | | `seconds` | `number` | the positive finite nominal duration in seconds. | #### Returns | Type | Description | | --- | --- | | `nil` | | #### Raises - when the duration is not positive and finite. ### `signal` _function_ ```nupp function signal(exclusive world: ecs.World, name: string): integer ``` Raises a named signal and wakes every playback blocked on it. Delivery happens on the next fixed step. Raising a signal nothing waits on is not an error and is not remembered: a playback that reaches `waitSignal` afterwards keeps waiting. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the signal state | | `name` | `string` | the signal name, registered nowhere | #### Returns | Type | Description | | --- | --- | | `integer` | the number of playbacks waiting on the name now, which may differ from the set the next fixed step wakes | #### Raises - when the name is empty ### `signalOnEvent` _function_ ```nupp function signalOnEvent(exclusive world: ecs.World, name: string, event: Type): nil ``` Raises a signal whenever an event emits at address zero. An ECS event is an edge, like a signal, so this wires one to the other rather than adding a separate kind of wait. Delivery follows the ordinary signal rule and waiters wake on the next fixed step. #### Type parameters | Name | Description | | --- | --- | | `E` | | #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the observer and the signal state | | `name` | `string` | the signal to raise, once per emission | | `event` | `Type\` | the event definition, observed at address zero and only there; the observer lasts for the life of the world | #### Returns | Type | Description | | --- | --- | | `nil` | | #### Raises - when the name is empty ### `sourceKey` _function_ ```nupp function sourceKey(key: string, component: ecs.Component, fields: {string}): TrackSource ``` Reads a moving destination from the live entity holding a world key. Missing or despawned sources contribute zero until a live entity claims the key. #### Arguments | Name | Type | Description | | --- | --- | --- | | `key` | `string` | the non-empty key resolved on every evaluation. | | `component` | `ecs.Component` | the component to read from that entity. | | `fields` | `{string}` | the fields aligned with the target's fields. | #### Returns | Type | Description | | --- | --- | | `TrackSource` | the keyed tracking source. | #### Raises - when the key is empty. ### `sourceOwn` _function_ ```nupp function sourceOwn(component: ecs.Component, fields: {string}): TrackSource ``` Reads a moving destination from the animated entity itself. #### Arguments | Name | Type | Description | | --- | --- | --- | | `component` | `ecs.Component` | the component read | | `fields` | `{string}` | the fields read, lined up with the target's own | #### Returns | Type | Description | | --- | --- | | `TrackSource` | the source | ### `sourceRelated` _function_ ```nupp function sourceRelated(relationship: ecs.Component, component: ecs.Component, fields: {string}): TrackSource ``` Reads a moving destination from the entity a relationship points at. #### Arguments | Name | Type | Description | | --- | --- | --- | | `relationship` | `ecs.Component` | the relationship traversed from the animated entity | | `component` | `ecs.Component` | the component read on the target entity | | `fields` | `{string}` | the fields read, lined up with the target's own | #### Returns | Type | Description | | --- | --- | | `TrackSource` | the source | ### `sourceTracking` _function_ ```nupp function sourceTracking(component: ecs.Component, fields: {string}): TrackSource ``` Reads a moving destination from the entity named by the animated entity's `TrackingTarget`. #### Arguments | Name | Type | Description | | --- | --- | --- | | `component` | `ecs.Component` | the component read | | `fields` | `{string}` | the fields read, lined up with the target's own | #### Returns | Type | Description | | --- | --- | | `TrackSource` | the source | ### `status` _function_ ```nupp function status(exclusive world: ecs.World, handle: Handle): Status? ``` Returns a playback's status. A finished playback still answers, with `state` saying how it ended, until a later `play` takes its slot. The waiting fields are filled only while the playback lives. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the playback | | `handle` | `Handle` | the playback to inspect, read against this world's cursor arena | #### Returns | Type | Description | | --- | --- | | `Status?` | a caller-owned status, or nil for a handle this world never issued | ### `targetAngle` _function_ ```nupp function targetAngle(component: ecs.Component, fieldName: string): Target ``` Interpolates one field as an angle, taking the short way round. #### Arguments | Name | Type | Description | | --- | --- | --- | | `component` | `ecs.Component` | the component whose field moves | | `fieldName` | `string` | the radian-valued field name | #### Returns | Type | Description | | --- | --- | | `Target` | the target | ### `targetField` _function_ ```nupp function targetField(component: ecs.Component, fieldName: string): Target ``` Interpolates one numeric field of a component. #### Arguments | Name | Type | Description | | --- | --- | --- | | `component` | `ecs.Component` | the component whose field moves | | `fieldName` | `string` | the field name | #### Returns | Type | Description | | --- | --- | | `Target` | the target, which holds no per-playback state and is safe to share | ### `targetField2` _function_ ```nupp function targetField2(component: ecs.Component, first: string, second: string): Target ``` Interpolates two numeric fields of a component together. #### Arguments | Name | Type | Description | | --- | --- | --- | | `component` | `ecs.Component` | the component whose fields move | | `first` | `string` | the field the first destination lines up with | | `second` | `string` | the field the second destination lines up with | #### Returns | Type | Description | | --- | --- | | `Target` | the target | ### `timeline` _function_ ```nupp function timeline(name: string, spec: {TimelineNode}, options: TimelineOptions?): Program ``` Compiles a tween timeline into a program under a stable name. The compiled slots travel in the program's constant pool, so a timeline is snapshot safe for the same reason every other program is. Play it with `play`, giving the entity it animates as the `owner`: a playback with no owner has nothing to write to and completes on its first tick. A playback reads four parameters, all optional: `mode` is `"once"`, `"loop"`, or `"pingPong"`; `count` is the passes a finite repeat makes; `speed` is a playback multiplier defaulting to one; and `delay` is the seconds to wait before the first frame. They are read when the playback builds its state, so a speed of zero or less, a negative delay, or a repeat of a zero-length timeline faults the playback with `actionError` rather than raising from `play`. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | the stable symbolic name, sharing `define`'s namespace and versioning | | `spec` | `{TimelineNode}` | the timeline operations in execution order | | `options` | `TimelineOptions?` | the clock the timeline is evaluated against, defaulting to `"presentation"`; `"fixed"` makes it deterministic from a snapshot alone at the cost of stepping at the simulation's rate | #### Returns | Type | Description | | --- | --- | | `Program` | the compiled program, also reachable by name through `program` | #### Raises - when the clock is neither `"fixed"` nor `"presentation"`, or an operation is invalid ### `tweenAdjust` _function_ ```nupp function tweenAdjust(duration: number, curve: EasingName | EasingFunction, target: TargetName | Target, t1: number, t2: number?, t3: number?, t4: number?): TimelineNode ``` Builds a timeline operation that interpolates by a delta from the starting value. #### Arguments | Name | Type | Description | | --- | --- | --- | | `duration` | `number` | the seconds it occupies, which must be greater than zero | | `curve` | `EasingName | EasingFunction` | a name from the built-in curves, or one of those curve values | | `target` | `TargetName | Target` | which component fields move and in which order | | `t1` | `number` | the signed change applied to the target's first field | | `t2` | `number?` | the change applied to the second field | | `t3` | `number?` | the change applied to the third field | | `t4` | `number?` | the change applied to the fourth field | #### Returns | Type | Description | | --- | --- | | `TimelineNode` | an operation for a timeline spec | #### Raises - when the curve names no built-in ### `tweenEmit` _function_ ```nupp function tweenEmit(name: string): TimelineNode ``` Builds a timeline operation that emits a named sequence event. It occupies no time, so what follows it starts at the same instant. The emission carries the entity the timeline is animating as its one argument and the timeline's own playback as its handle. It fires as the cursor passes the point going forward, so a ping-pong return leg does not fire it a second time. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | the name carried on the emission | #### Returns | Type | Description | | --- | --- | | `TimelineNode` | an operation for a timeline spec | ### `tweenParallel` _function_ ```nupp function tweenParallel(blocks: {{TimelineNode}}): TimelineNode ``` Builds a timeline operation that runs blocks concurrently and ends with the longest. Every block starts where the operation sits, and what follows starts after the last of them ends. Two blocks writing the same component field is not an error, and the later one in argument order wins each tick. #### Arguments | Name | Type | Description | | --- | --- | --- | | `blocks` | `{{TimelineNode}}` | one block per concurrent branch, each run in sequence within itself | #### Returns | Type | Description | | --- | --- | | `TimelineNode` | an operation for a timeline spec | ### `tweenRun` _function_ ```nupp function tweenRun(spec: {TimelineNode}, options: RunOptions?): TimelineNode ``` Builds a timeline operation that runs a nested timeline from its own spec. The nested timeline occupies a window of the parent equal to its own length times its pass count, so a repeating nested run needs a finite `count`. Its operations keep their per-playback state separately from the parent's. #### Arguments | Name | Type | Description | | --- | --- | --- | | `spec` | `{TimelineNode}` | the nested operations, which this call reads rather than rewrites | | `options` | `RunOptions?` | omit to run the nested timeline once; `"loop"` and `"pingPong"` need a `count` here | #### Returns | Type | Description | | --- | --- | | `TimelineNode` | an operation for a timeline spec | #### Raises - when a repeating nested run carries no finite count ### `tweenTo` _function_ ```nupp function tweenTo(duration: number, curve: EasingName | EasingFunction, target: TargetName | Target, t1: number, t2: number?, t3: number?, t4: number?): TimelineNode ``` Builds a timeline operation that interpolates to an absolute destination. The operation reads its starting values from the entity on its first tick rather than during compilation, so the same timeline played on two entities starts from wherever each of them is. #### Arguments | Name | Type | Description | | --- | --- | --- | | `duration` | `number` | the seconds it occupies, which must be greater than zero | | `curve` | `EasingName | EasingFunction` | a name from the built-in curves, or one of those curve values | | `target` | `TargetName | Target` | which component fields move and in which order the destinations line up with them | | `t1` | `number` | the destination for the target's first field, in that field's own units: pixels for a translate, radians for a rotation, zero through one for a color channel | | `t2` | `number?` | the destination for the second field | | `t3` | `number?` | the destination for the third field | | `t4` | `number?` | the destination for the fourth field, with anything past the target's field count ignored and an omitted field treated as zero | #### Returns | Type | Description | | --- | --- | | `TimelineNode` | an operation for a timeline spec | #### Raises - when the curve names no built-in ### `tweenTrack` _function_ ```nupp function tweenTrack(duration: number, curve: EasingName | EasingFunction, target: TargetName | Target, from: TrackSource): TimelineNode ``` Builds a timeline operation that interpolates toward a destination that keeps moving. The first tick fixes the start as `tweenTo` does, and each later tick reads the destination again while the operation remains inside its window. Once the window ends the operation holds its last destination. A source whose entity or component is missing reads as zero rather than faulting. #### Arguments | Name | Type | Description | | --- | --- | --- | | `duration` | `number` | the seconds it occupies, which must be greater than zero | | `curve` | `EasingName | EasingFunction` | a name from the built-in curves, or one of those curve values | | `target` | `TargetName | Target` | which component fields move and which fields of the source line up with them | | `from` | `TrackSource` | where the destination is read each tick | #### Returns | Type | Description | | --- | --- | | `TimelineNode` | an operation for a timeline spec | #### Raises - when the curve names no built-in ### `tweenWait` _function_ ```nupp function tweenWait(duration: number): TimelineNode ``` Builds a timeline operation that advances the cursor without changing anything. #### Arguments | Name | Type | Description | | --- | --- | --- | | `duration` | `number` | the seconds it occupies, where zero performs no work | #### Returns | Type | Description | | --- | --- | | `TimelineNode` | an operation for a timeline spec | ### `upcoming` _function_ ```nupp function upcoming(exclusive world: ecs.World, handle: Handle, withinTicks: integer?): {Step} ``` Returns the actions and emissions a playback will certainly perform next, and their timing. The walk covers the straight-line run ahead of where the playback sits, accumulating waits, and stops at the first instruction whose successor requires execution. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the playback | | `handle` | `Handle` | the playback to inspect | | `withinTicks` | `integer?` | report only what is due within this many ticks of the playback's own clock, or nil for everything the walk can reach | #### Returns | Type | Description | | --- | --- | | `{Step}` | a caller-owned list of the calls and emissions ahead, in order; empty for a handle that names nothing running and for one parked on a signal, a query, a join, a tween, or an evaluator, since none of those has a predictable start. A wait written in seconds also ends the walk. | ### `wait` _function_ ```nupp function wait(seconds: number): Node ``` Builds a step that waits a duration in seconds. The duration converts to whole ticks when the instruction runs, rounded to nearest, and any non-zero duration waits at least one tick. Zero still costs a tick: the cursor resumes on the program's next tick rather than carrying on within this one. #### Arguments | Name | Type | Description | | --- | --- | --- | | `seconds` | `number` | the non-negative duration | #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | #### Raises - when the duration is negative ### `waitingOn` _function_ ```nupp function waitingOn(exclusive world: ecs.World, name: string): integer ``` Returns how many playbacks currently wait on a signal name. #### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive world` | `ecs.World` | the world that owns the waiting playbacks | | `name` | `string` | the signal name to count | #### Returns | Type | Description | | --- | --- | | `integer` | zero for a name nothing waits on; a signal raised during this step leaves its waiters in the count until the next step delivers it | ### `waitQuery` _function_ ```nupp function waitQuery(name: string, condition: QueryCondition): Node ``` Builds a step that blocks until a registered query matches or stops matching. Unlike a signal, which is an edge, this is a condition on the world: a wait whose condition already holds resumes rather than waiting for a transition that has already happened. The condition is evaluated at the start of a fixed step rather than at the instruction, so a query wait costs at least one step. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | the registered query name, resolved per world when the instruction runs | | `condition` | `QueryCondition` | `"any"` to wait for a match or `"empty"` to wait for none | #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | #### Raises - when the name is empty or the condition is neither value ### `waitSignal` _function_ ```nupp function waitSignal(name: string): Node ``` Builds a step that blocks until `signal` raises a named signal. The next fixed step delivers signals after `signal` runs, so a signal one sequence raises never runs another within the same step. A signal raised before the wait is not remembered. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | the signal name, which is registered nowhere | #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | #### Raises - when the name is empty ### `waitSteps` _function_ ```nupp function waitSteps(steps: integer): Node ``` Builds a step that waits a whole number of ticks of the program's clock. #### Arguments | Name | Type | Description | | --- | --- | --- | | `steps` | `integer` | the non-negative tick count, where zero yields until the next tick | #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | #### Raises - when the count is negative or not a whole number ### `waitTween` _function_ ```nupp function waitTween(): Node ``` Builds a step that waits for the playback the most recent `playTween` started. It resumes when that specific playback completes, is canceled, loses its channel, or loses its entity, so it never waits forever, and `status` reports the outcome as `tweenOutcome`. A `waitTween` that no `playTween` preceded falls straight through without costing a tick. #### Returns | Type | Description | | --- | --- | | `Node` | a step for `define`, not to be put in a second program | ## Values ### `DEFAULT_BUDGET` _variable_ ```nupp const DEFAULT_BUDGET: integer ``` The per-tick instruction budget a world gives a playback that asks for none. ### `TrackingTarget` _variable_ ```nupp const TrackingTarget: components.TableComponent ``` The process-wide component a `tweenTrack` tracking source reads.