
# tecs.gfx.animation


Sprite sheets, fixed-step playback, Aseprite slices, pivots, and reloads.

A [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) divides one image into frames and
names frame ranges with tags. An
[`Animation`](/modules/gfx/animation/#tecs.gfx.animation.Animation) selects a sheet tag and
carries speed, loop, and playback state.

```teal
local hero <const> = tecs.gfx.animation.newGridSheet({
    name = "hero",
    imageWidth = 256,
    imageHeight = 32,
    frameWidth = 32,
    frameHeight = 32,
    tags = {
        idle = {from = 1, to = 4},
        run = {from = 5, to = 8},
    },
})

hero:bind(app.renderer.sprites:sprite("hero.png"))
world:addPlugin(tecs.gfx.animation.plugin)

world:spawn(
    tecs.Transform2D(64, 64, 0, 1, 0, 32, 32),
    hero:sprite(),
    tecs.gfx.animation.of(hero, "run"),
    tecs.gfx.Renderable2D()
)
```

Playback advances in fixed steps. Machines that replay the same simulation
therefore select the same frames. `frameOf` and `timeOf` report playback on
the same fixed-step clock.

## Sheet sources

Use `newGridSheet` for uniform cells, `newRectSheet` for an explicit frame
list, `newSheetBuilder` for a custom sheet, or `newSheetFromAseprite` for an
Aseprite JSON export. Frames count from one. Tags name inclusive frame spans
and may play forward, reverse, or ping-pong.

Bind a sheet to a renderer sprite before drawing it. Every entity playing that
sheet shares its frame and timing data.

## Slices and pivots

Aseprite slices may move between frames. A
[`Pivot`](/modules/gfx/animation/#tecs.gfx.animation.Pivot) bound to a slice follows that
movement, which keeps attachments such as hands, muzzles, and feet on the part
of the drawing they name.

## Reloads

Re-exporting a sheet under the same name can replace its frame, tag, slice, and
timing data in place. Existing entities retain the sheet id and continue from
their playback state. A replacement must preserve the bound image dimensions.

A sprite sheet divides one image into frames, tags, and slices.

Aseprite supplies the model: each frame carries its own duration, tags play
inclusive spans in a direction, and slices carry rectangles, nine-slice
centers, and pivots that may move between frames. `fromAseprite` reads its JSON
export into the same interface that `grid`, `rects`, and `build` produce.

Frames count from one in sheet order. Tag zero represents the whole sheet
playing forward.

Bind the finished sheet to a renderer sprite before drawing:

```teal
local hero <const> = tecs.gfx.animation.newSheetFromAseprite({
    name = "game.hero",
    json = asepriteExport,
})

hero:bind(app.renderer.sprites:sprite("sprites/hero.png"))
```

`sprite(frame)` creates a [`Sprite`](/modules/gfx/#tecs.gfx.Sprite) for one frame.
`pivot(name, frame)` creates a
[`Pivot`](/modules/gfx/animation/#tecs.gfx.animation.Pivot) from a slice. Animation keeps that
pivot on the named slice as the slice moves.

A sheet name forms a snapshot compatibility surface. Every entity that plays
the sheet shares its registered frame, tag, slice, and timing data.

## Module contents

### Constructors

| Constructor | Description |
| --- | --- |
| [`newGridSheet`](/modules/gfx/animation/#tecs.gfx.animation.newGridSheet) | Creates a sheet whose frames form a uniform grid. |
| [`newRectSheet`](/modules/gfx/animation/#tecs.gfx.animation.newRectSheet) | Creates a sheet from explicitly listed frame rectangles. |
| [`newSheetBuilder`](/modules/gfx/animation/#tecs.gfx.animation.newSheetBuilder) | Creates a builder for a sheet that the other constructors cannot describe. |
| [`newSheetFromAseprite`](/modules/gfx/animation/#tecs.gfx.animation.newSheetFromAseprite) | Creates a sheet from an Aseprite JSON export. |

### Types

| Type | Kind | Description |
| --- | --- | --- |
| [`Animation`](/modules/gfx/animation/#tecs.gfx.animation.Animation) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Stores playback state for one entity. |
| [`AnimationEvents`](/modules/gfx/animation/#tecs.gfx.animation.AnimationEvents) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Requests Completed and Looped events for an entity. |
| [`AsepriteOptions`](/modules/gfx/animation/#tecs.gfx.animation.AsepriteOptions) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Configures newSheetFromAseprite. |
| [`Builder`](/modules/gfx/animation/#tecs.gfx.animation.Builder) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Builds custom sheets one frame at a time. |
| [`Completed`](/modules/gfx/animation/#tecs.gfx.animation.Completed) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Reports when a non-looping tag runs past its last frame. |
| [`Direction`](/modules/gfx/animation/#tecs.gfx.animation.Direction) | <span class="tealdoc-kind-badge tealdoc-kind-enum">enum</span> | Selects how a tag walks its span. |
| [`GridOptions`](/modules/gfx/animation/#tecs.gfx.animation.GridOptions) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Configures newGridSheet. |
| [`Looped`](/modules/gfx/animation/#tecs.gfx.animation.Looped) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Reports when a looping tag passes its last frame and restarts. |
| [`Pivot`](/modules/gfx/animation/#tecs.gfx.animation.Pivot) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Read-only. Exposes the pivot component that controls where an entity's quad turns and scales. |
| [`PlayOptions`](/modules/gfx/animation/#tecs.gfx.animation.PlayOptions) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Configures of and play. |
| [`Rect`](/modules/gfx/animation/#tecs.gfx.animation.Rect) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | One frame, as newRectSheet and the builder take it. |
| [`RectsOptions`](/modules/gfx/animation/#tecs.gfx.animation.RectsOptions) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Configures newRectSheet. |
| [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Read-only. Exposes an image divided into frames. |
| [`Slice`](/modules/gfx/animation/#tecs.gfx.animation.Slice) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | A named region that moves across the frames. |
| [`SliceKey`](/modules/gfx/animation/#tecs.gfx.animation.SliceKey) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Defines where a slice sits from one frame onward. |
| [`Tag`](/modules/gfx/animation/#tecs.gfx.animation.Tag) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | A named span of frames, as the constructors take it. |

### Functions

| Function | Kind | Description |
| --- | --- | --- |
| [`build`](/modules/gfx/animation/#tecs.gfx.animation.build) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Creates a builder for a sheet that the other constructors cannot describe. |
| [`byId`](/modules/gfx/animation/#tecs.gfx.animation.byId) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Returns the sheet represented by a registration index, or nil. |
| [`byName`](/modules/gfx/animation/#tecs.gfx.animation.byName) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Returns the sheet registered under a name, or nil. |
| [`findSheetById`](/modules/gfx/animation/#tecs.gfx.animation.findSheetById) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Returns the sheet represented by a process-wide id. |
| [`findSheetByName`](/modules/gfx/animation/#tecs.gfx.animation.findSheetByName) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Returns the sheet registered under a name. |
| [`frameOf`](/modules/gfx/animation/#tecs.gfx.animation.frameOf) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Returns the sheet frame shown by an entity's animation. |
| [`fromAseprite`](/modules/gfx/animation/#tecs.gfx.animation.fromAseprite) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Creates a sheet from an Aseprite JSON export. |
| [`grid`](/modules/gfx/animation/#tecs.gfx.animation.grid) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Creates a sheet whose frames form a uniform grid. |
| [`of`](/modules/gfx/animation/#tecs.gfx.animation.of) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Creates an Animation that plays a named sheet tag and is ready to spawn. |
| [`play`](/modules/gfx/animation/#tecs.gfx.animation.play) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Points a live entity at a tag and restarts it there. |
| [`plugin`](/modules/gfx/animation/#tecs.gfx.animation.plugin) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Adds the systems that drive playback. |
| [`rects`](/modules/gfx/animation/#tecs.gfx.animation.rects) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Creates a sheet from explicitly listed frame rectangles. |
| [`replace`](/modules/gfx/animation/#tecs.gfx.animation.replace) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Folds a re-exported sheet into the one already registered under its name, in place, so an entity playing the old id... |
| [`restart`](/modules/gfx/animation/#tecs.gfx.animation.restart) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Plays an entity's animation again from the start of its tag. |
| [`revision`](/modules/gfx/animation/#tecs.gfx.animation.revision) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Returns how many times any sheet's frames have changed. |
| [`sheetRevision`](/modules/gfx/animation/#tecs.gfx.animation.sheetRevision) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Returns how many times any sheet's frames have changed. |
| [`timeOf`](/modules/gfx/animation/#tecs.gfx.animation.timeOf) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Returns an animation's position in its tag cycle, in seconds. |

### Values

| Value | Type | Description |
| --- | --- | --- |
| [`DEFAULT_DURATION`](/modules/gfx/animation/#tecs.gfx.animation.DEFAULT_DURATION) | `number` | Read-only. Reports how many milliseconds a frame remains visible when nothing overrides its duration. |

## Constructors

<a id="tecs.gfx.animation.newGridSheet"></a>
### tecs.gfx.animation.newGridSheet <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates a sheet whose frames form a uniform grid.


```teal
function tecs.gfx.animation.newGridSheet(
    options: sheet.GridOptions
): sheet.Sheet
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `options` | [`sheet.GridOptions`](/modules/gfx/animation/#tecs.gfx.animation.GridOptions) | Raises on a missing name, a non-positive image or frame size, a grid that fits no cells, or a `count` past what the grid holds. Frames come out in row-major order. |

#### Returns

| Type | Description |
| --- | --- |
| [`sheet.Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The finished sheet, already registered under its name and carrying an `id`. |

<a id="tecs.gfx.animation.newRectSheet"></a>
### tecs.gfx.animation.newRectSheet <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates a sheet from explicitly listed frame rectangles.


```teal
function tecs.gfx.animation.newRectSheet(
    options: sheet.RectsOptions
): sheet.Sheet
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `options` | [`sheet.RectsOptions`](/modules/gfx/animation/#tecs.gfx.animation.RectsOptions) | Raises on a missing name, a non-positive image size, an empty frame list, or a frame with no positive size. |

#### Returns

| Type | Description |
| --- | --- |
| [`sheet.Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The finished sheet, already registered under its name and carrying an `id`. |

<a id="tecs.gfx.animation.newSheetBuilder"></a>
### tecs.gfx.animation.newSheetBuilder <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates a builder for a sheet that the other constructors cannot
describe.


```teal
function tecs.gfx.animation.newSheetBuilder(
    name: string, imageWidth: number, imageHeight: number
): sheet.Builder
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `name` | `string` | Name to register the finished sheet under. |
| `imageWidth` | `number` | Size of the image the frames are cut from, in pixels. |
| `imageHeight` | `number` | The other size, in pixels. |

#### Returns

| Type | Description |
| --- | --- |
| [`sheet.Builder`](/modules/gfx/animation/#tecs.gfx.animation.Builder) | Returns a builder that registers the sheet when `finish` runs. |

<a id="tecs.gfx.animation.newSheetFromAseprite"></a>
### tecs.gfx.animation.newSheetFromAseprite <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates a sheet from an Aseprite JSON export.


```teal
function tecs.gfx.animation.newSheetFromAseprite(
    options: sheet.AsepriteOptions
): sheet.Sheet
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `options` | [`sheet.AsepriteOptions`](/modules/gfx/animation/#tecs.gfx.animation.AsepriteOptions) | Raises on a missing name or an export the reader cannot make a sheet out of. |

#### Returns

| Type | Description |
| --- | --- |
| [`sheet.Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The finished sheet, already registered. |

## Types

<a id="tecs.gfx.animation.Animation"></a>
### tecs.gfx.animation.Animation <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Stores playback state for one entity.

What an entity is playing lives here and where its cycle has got to lives in
its [`Sprite`](/modules/gfx/#tecs.gfx.Sprite), which carries the playback
the shader resolves. So `frame` is not an index: the encoder writes
`ENCODED` to say the [`Sprite`](/modules/gfx/#tecs.gfx.Sprite) carries a
live playback, and zero says the entity is to start its cycle again. Which
frame is showing is `animation.frameOf`.

`time` is the phase the cycle starts or resumes from, in seconds, and stays
inside the cycle. Nothing advances it while playback runs, so it neither
grows without bound nor loses precision to its own age.
Read-only. Exposes the playback-state component for one entity.


```teal
record tecs.gfx.animation.Animation is Component
    sheet: number
    tag: number
    speed: number
    time: number
    frame: number
    loop: boolean
    playing: boolean
end
```

#### Interfaces

| Interface |
| --- |
| [`Component`](/modules/ecs/#tecs.ecs.Component) |

<a id="tecs.gfx.animation.Animation.sheet"></a>
#### tecs.gfx.animation.Animation.sheet <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Selects a sheet by its `Sheet.id` registration index.
Zero plays nothing.


```teal
tecs.gfx.animation.Animation.sheet: number
```

<a id="tecs.gfx.animation.Animation.tag"></a>
#### tecs.gfx.animation.Animation.tag <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Selects a tag by its `Sheet:tagId` index. Zero plays the
whole sheet in order.


```teal
tecs.gfx.animation.Animation.tag: number
```

<a id="tecs.gfx.animation.Animation.speed"></a>
#### tecs.gfx.animation.Animation.speed <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Multiplies the timing the sheet carries. One is the timing as
authored, two is twice as fast. Zero or less holds the current frame and
stops time advancing, which is a pause that leaves `playing` alone.

How long each frame is held is the sheet's answer and not an entity's,
because that is where an artist sets it: a hold frame is a frame with a
long duration, which no single rate can express.


```teal
tecs.gfx.animation.Animation.speed: number
```

<a id="tecs.gfx.animation.Animation.time"></a>
#### tecs.gfx.animation.Animation.time <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Engine-owned. Carries the phase the cycle starts or resumes from, in
seconds. Ordinary game code should read `timeOf`, which reports where the
cycle has got to; this field stays where playback was last started from.
The cycle duration is the sum of the durations of the frames the tag
visits. Changing `speed` leaves the phase where it is, so playback
carries on from the frame it was showing rather than jumping.


```teal
tecs.gfx.animation.Animation.time: number
```

<a id="tecs.gfx.animation.Animation.frame"></a>
#### tecs.gfx.animation.Animation.frame <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Engine-owned. Says whether the Sprite carries a live playback, and never
which frame that playback is showing. Ordinary game code should use
`frameOf`. Zero asks for the cycle to start again, which is what `play`,
`restart`, `of` and a restored snapshot write.


```teal
tecs.gfx.animation.Animation.frame: number
```

<a id="tecs.gfx.animation.Animation.loop"></a>
#### tecs.gfx.animation.Animation.loop <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Controls whether the tag restarts after its last frame.


```teal
tecs.gfx.animation.Animation.loop: boolean
```

<a id="tecs.gfx.animation.Animation.playing"></a>
#### tecs.gfx.animation.Animation.playing <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Controls whether time advances.


```teal
tecs.gfx.animation.Animation.playing: boolean
```

<a id="tecs.gfx.animation.AnimationEvents"></a>
### tecs.gfx.animation.AnimationEvents <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Requests [`Completed`](/modules/gfx/animation/#tecs.gfx.animation.Completed) and
[`Looped`](/modules/gfx/animation/#tecs.gfx.animation.Looped) events for an entity.

The event query visits only entities carrying this tag. A game can request
events for a handful of entities without walking the rest of its animated
crowd. Adding the tag costs one archetype move and nothing per step.
Read-only. Exposes the tag that requests
[`Completed`](/modules/gfx/animation/#tecs.gfx.animation.Completed) and
[`Looped`](/modules/gfx/animation/#tecs.gfx.animation.Looped) events for an entity.


```teal
record tecs.gfx.animation.AnimationEvents is Component
end
```

#### Interfaces

| Interface |
| --- |
| [`Component`](/modules/ecs/#tecs.ecs.Component) |

<a id="tecs.gfx.animation.AsepriteOptions"></a>
### tecs.gfx.animation.AsepriteOptions <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Configures `newSheetFromAseprite`.


```teal
record tecs.gfx.animation.AsepriteOptions
    name: string
    json: any
end
```

<a id="tecs.gfx.animation.AsepriteOptions.name"></a>
#### tecs.gfx.animation.AsepriteOptions.name <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the registration name. It defaults to the export's
image name. An export without an image name requires this field.


```teal
tecs.gfx.animation.AsepriteOptions.name: string
```

<a id="tecs.gfx.animation.AsepriteOptions.json"></a>
#### tecs.gfx.animation.AsepriteOptions.json <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Supplies the export as JSON text or a decoded table.
it. A table is what an asset pipeline that decoded once should pass.


```teal
tecs.gfx.animation.AsepriteOptions.json: any
```

<a id="tecs.gfx.animation.Builder"></a>
### tecs.gfx.animation.Builder <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Builds custom sheets one frame at a time.


```teal
record tecs.gfx.animation.Builder
    finish: function(self): Sheet
    frame: function(
        self,
        x: number,
        y: number,
        w: number,
        h: number,
        duration: number
    ): Builder
    slice: function(
        self,
        name: string,
        x: number,
        y: number,
        w: number,
        h: number,
        pivotX: number,
        pivotY: number
    ): Builder
    sliceKeys: function(
        self, name: string, data: string, keys: {SliceKey}
    ): Builder
    tag: function(
        self,
        name: string,
        from: integer,
        to: integer,
        direction: Direction
    ): Builder
end
```

<a id="tecs.gfx.animation.Builder.finish"></a>
#### tecs.gfx.animation.Builder:finish <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Registers and returns the finished sheet.

Raises on a sheet with no frames, and on a tag whose span falls outside
them.


```teal
function tecs.gfx.animation.Builder.finish(self): Sheet
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Builder` |  |

##### Returns

| Type | Description |
| --- | --- |
| [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) |  |

<a id="tecs.gfx.animation.Builder.frame"></a>
#### tecs.gfx.animation.Builder:frame <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Appends a frame to the sheet under construction.


```teal
function tecs.gfx.animation.Builder.frame(
    self, x: number, y: number, w: number, h: number, duration: number
): Builder
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Builder` |  |
| `x` | `number` | Left of the frame in the image, in pixels. |
| `y` | `number` | Top of the frame. |
| `w` | `number` | Width, which must be positive. |
| `h` | `number` | Height, which must be positive. |
| `duration` | `number` | Milliseconds it is held. Defaults to `sheet.DEFAULT_DURATION`. |

##### Returns

| Type | Description |
| --- | --- |
| [`Builder`](/modules/gfx/animation/#tecs.gfx.animation.Builder) | The builder. |

<a id="tecs.gfx.animation.Builder.slice"></a>
#### tecs.gfx.animation.Builder:slice <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Adds a fixed slice with a pivot.


```teal
function tecs.gfx.animation.Builder.slice(
    self,
    name: string,
    x: number,
    y: number,
    w: number,
    h: number,
    pivotX: number,
    pivotY: number
): Builder
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Builder` |  |
| `name` | `string` | What a sprite names to take its pivot from. |
| `x` | `number` | Left of the slice within a frame, in pixels. |
| `y` | `number` | Top of the slice. |
| `w` | `number` | Width. |
| `h` | `number` | Height. |
| `pivotX` | `number` | Pivot within the slice, in the slice's own pixels. Omitted, the slice carries no pivot and its middle stands in. |
| `pivotY` | `number` |  |

##### Returns

| Type | Description |
| --- | --- |
| [`Builder`](/modules/gfx/animation/#tecs.gfx.animation.Builder) | The builder. |

<a id="tecs.gfx.animation.Builder.sliceKeys"></a>
#### tecs.gfx.animation.Builder:sliceKeys <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Adds a slice from explicit keys for importers.


```teal
function tecs.gfx.animation.Builder.sliceKeys(
    self, name: string, data: string, keys: {SliceKey}
): Builder
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Builder` |  |
| `name` | `string` | The slice's name. |
| `data` | `string` | Free text to carry alongside it, or nil for none. |
| `keys` | `{`[`SliceKey`](/modules/gfx/animation/#tecs.gfx.animation.SliceKey)`}` | Keys in frame order, at least one. |

##### Returns

| Type | Description |
| --- | --- |
| [`Builder`](/modules/gfx/animation/#tecs.gfx.animation.Builder) | The builder. |

<a id="tecs.gfx.animation.Builder.tag"></a>
#### tecs.gfx.animation.Builder:tag <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Names an inclusive frame span and its playback direction.


```teal
function tecs.gfx.animation.Builder.tag(
    self, name: string, from: integer, to: integer, direction: Direction
): Builder
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Builder` |  |
| `name` | `string` | What an animation asks for. |
| `from` | `integer` | First frame, counting from one. |
| `to` | `integer` | Last frame, inclusive. |
| `direction` | [`Direction`](/modules/gfx/animation/#tecs.gfx.animation.Direction) | Defaults to "forward". |

##### Returns

| Type | Description |
| --- | --- |
| [`Builder`](/modules/gfx/animation/#tecs.gfx.animation.Builder) | The builder. |

<a id="tecs.gfx.animation.Completed"></a>
### tecs.gfx.animation.Completed <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Reports when a non-looping tag runs past its
last frame. The animation stops and holds that frame, so this fires once per
playthrough and never again until something restarts it.
Read-only. Exposes the event emitted when a non-looping tag finishes.


```teal
record tecs.gfx.animation.Completed is events.Event
    entity: integer
    sheet: Sheet
    tag: string

    metamethod __call: function(
        self, entity: integer, sheet: Sheet, tag: string
    ): Completed
end
```

#### Interfaces

| Interface |
| --- |
| [`events.Event`](/modules/events/#tecs.events.Event) |

<a id="tecs.gfx.animation.Completed.entity"></a>
#### tecs.gfx.animation.Completed.entity <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Identifies the entity whose animation completed.


```teal
tecs.gfx.animation.Completed.entity: integer
```

<a id="tecs.gfx.animation.Completed.sheet"></a>
#### tecs.gfx.animation.Completed.sheet <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Reports the sheet that completed.


```teal
tecs.gfx.animation.Completed.sheet: Sheet
```

<a id="tecs.gfx.animation.Completed.tag"></a>
#### tecs.gfx.animation.Completed.tag <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Reports the tag that finished, or the empty string for a
whole sheet.


```teal
tecs.gfx.animation.Completed.tag: string
```

<a id="tecs.gfx.animation.Completed.$meta"></a>
<a id="tecs.gfx.animation.Completed.$meta.__call"></a>
#### tecs.gfx.animation.Completed:__call <span class="tealdoc-kind-badge tealdoc-kind-metamethod">metamethod</span>

Creates a completed event value.


```teal
metamethod tecs.gfx.animation.Completed.$meta.__call(
    self, entity: integer, sheet: Sheet, tag: string
): Completed
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Completed` | The completed event type. |
| `entity` | `integer` | The entity whose animation completed. |
| `sheet` | [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The sheet that completed. |
| `tag` | `string` | The tag that completed, or an empty string for the whole sheet. |

##### Returns

| Type | Description |
| --- | --- |
| [`Completed`](/modules/gfx/animation/#tecs.gfx.animation.Completed) | The completed event value. |

<a id="tecs.gfx.animation.Direction"></a>
### tecs.gfx.animation.Direction <span class="tealdoc-kind-badge tealdoc-kind-enum">enum</span>

Selects how a tag walks its span.


```teal
enum tecs.gfx.animation.Direction
    "forward"
    "pingpong"
    "reverse"
end
```

<a id="tecs.gfx.animation.GridOptions"></a>
### tecs.gfx.animation.GridOptions <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Configures `newGridSheet`.


```teal
record tecs.gfx.animation.GridOptions
    name: string
    imageWidth: number
    imageHeight: number
    frameWidth: number
    frameHeight: number
    margin: number
    spacing: number
    columns: integer
    rows: integer
    count: integer
    duration: number
    tags: {string: Tag}
    slices: {Slice}
end
```

<a id="tecs.gfx.animation.GridOptions.name"></a>
#### tecs.gfx.animation.GridOptions.name <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the required registration name.


```teal
tecs.gfx.animation.GridOptions.name: string
```

<a id="tecs.gfx.animation.GridOptions.imageWidth"></a>
#### tecs.gfx.animation.GridOptions.imageWidth <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the required image width in pixels.


```teal
tecs.gfx.animation.GridOptions.imageWidth: number
```

<a id="tecs.gfx.animation.GridOptions.imageHeight"></a>
#### tecs.gfx.animation.GridOptions.imageHeight <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the required image height in pixels.


```teal
tecs.gfx.animation.GridOptions.imageHeight: number
```

<a id="tecs.gfx.animation.GridOptions.frameWidth"></a>
#### tecs.gfx.animation.GridOptions.frameWidth <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the required frame width in pixels.


```teal
tecs.gfx.animation.GridOptions.frameWidth: number
```

<a id="tecs.gfx.animation.GridOptions.frameHeight"></a>
#### tecs.gfx.animation.GridOptions.frameHeight <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the required frame height in pixels.


```teal
tecs.gfx.animation.GridOptions.frameHeight: number
```

<a id="tecs.gfx.animation.GridOptions.margin"></a>
#### tecs.gfx.animation.GridOptions.margin <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the border between the image edge and first cell.
Defaults to zero.


```teal
tecs.gfx.animation.GridOptions.margin: number
```

<a id="tecs.gfx.animation.GridOptions.spacing"></a>
#### tecs.gfx.animation.GridOptions.spacing <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the gap between neighboring cells and defaults to
zero.


```teal
tecs.gfx.animation.GridOptions.spacing: number
```

<a id="tecs.gfx.animation.GridOptions.columns"></a>
#### tecs.gfx.animation.GridOptions.columns <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets how many cells fit across. The constructor derives
it from the image size when omitted.


```teal
tecs.gfx.animation.GridOptions.columns: integer
```

<a id="tecs.gfx.animation.GridOptions.rows"></a>
#### tecs.gfx.animation.GridOptions.rows <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets how many cells fit down. The constructor derives
it from the image size when omitted.


```teal
tecs.gfx.animation.GridOptions.rows: integer
```

<a id="tecs.gfx.animation.GridOptions.count"></a>
#### tecs.gfx.animation.GridOptions.count <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets how many frames to take across rows. It defaults to every cell, which is
wrong only for a sheet whose last row is short.


```teal
tecs.gfx.animation.GridOptions.count: integer
```

<a id="tecs.gfx.animation.GridOptions.duration"></a>
#### tecs.gfx.animation.GridOptions.duration <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets how many milliseconds every cell remains visible.
It defaults to `DEFAULT_DURATION`. A grid uses one duration for every
frame; retime individual frames with `sheet.build`.


```teal
tecs.gfx.animation.GridOptions.duration: number
```

<a id="tecs.gfx.animation.GridOptions.tags"></a>
#### tecs.gfx.animation.GridOptions.tags <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Defines optional named tags over the frames.


```teal
tecs.gfx.animation.GridOptions.tags: {string: Tag}
```

<a id="tecs.gfx.animation.GridOptions.slices"></a>
#### tecs.gfx.animation.GridOptions.slices <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Defines optional named slices.


```teal
tecs.gfx.animation.GridOptions.slices: {Slice}
```

<a id="tecs.gfx.animation.Looped"></a>
### tecs.gfx.animation.Looped <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Reports when a looping tag passes its last frame
and restarts.

Once per step at most, not once per cycle: a step long enough to cover
several cycles wraps the time once and reports one loop, so counting these
is not a way to count playthroughs.
Read-only. Exposes the event emitted when a looping tag restarts.


```teal
record tecs.gfx.animation.Looped is events.Event
    entity: integer
    sheet: Sheet
    tag: string

    metamethod __call: function(
        self, entity: integer, sheet: Sheet, tag: string
    ): Looped
end
```

#### Interfaces

| Interface |
| --- |
| [`events.Event`](/modules/events/#tecs.events.Event) |

<a id="tecs.gfx.animation.Looped.entity"></a>
#### tecs.gfx.animation.Looped.entity <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Identifies the entity whose animation looped.


```teal
tecs.gfx.animation.Looped.entity: integer
```

<a id="tecs.gfx.animation.Looped.sheet"></a>
#### tecs.gfx.animation.Looped.sheet <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Reports the sheet that looped.


```teal
tecs.gfx.animation.Looped.sheet: Sheet
```

<a id="tecs.gfx.animation.Looped.tag"></a>
#### tecs.gfx.animation.Looped.tag <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Reports the tag that wrapped, or the empty string for a
whole sheet.


```teal
tecs.gfx.animation.Looped.tag: string
```

<a id="tecs.gfx.animation.Looped.$meta"></a>
<a id="tecs.gfx.animation.Looped.$meta.__call"></a>
#### tecs.gfx.animation.Looped:__call <span class="tealdoc-kind-badge tealdoc-kind-metamethod">metamethod</span>

Creates a looped event value.


```teal
metamethod tecs.gfx.animation.Looped.$meta.__call(
    self, entity: integer, sheet: Sheet, tag: string
): Looped
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Looped` | The looped event type. |
| `entity` | `integer` | The entity whose animation looped. |
| `sheet` | [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The sheet that looped. |
| `tag` | `string` | The tag that looped, or an empty string for the whole sheet. |

##### Returns

| Type | Description |
| --- | --- |
| [`Looped`](/modules/gfx/animation/#tecs.gfx.animation.Looped) | The looped event value. |

<a id="tecs.gfx.animation.Pivot"></a>
### tecs.gfx.animation.Pivot <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Read-only. Exposes the pivot component that controls where an entity's
quad turns and scales.


```teal
record tecs.gfx.animation.Pivot is Component
    x: number
    y: number
    sheet: number
    slice: number
    halfX: number
    halfY: number
end
```

#### Interfaces

| Interface |
| --- |
| [`Component`](/modules/ecs/#tecs.ecs.Component) |

<a id="tecs.gfx.animation.Pivot.x"></a>
#### tecs.gfx.animation.Pivot.x <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the pivot as a fraction across the frame from its
left edge. One half selects the middle.


```teal
tecs.gfx.animation.Pivot.x: number
```

<a id="tecs.gfx.animation.Pivot.y"></a>
#### tecs.gfx.animation.Pivot.y <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the pivot as a fraction down the frame from its
top edge. One half selects the middle.


```teal
tecs.gfx.animation.Pivot.y: number
```

<a id="tecs.gfx.animation.Pivot.sheet"></a>
#### tecs.gfx.animation.Pivot.sheet <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Selects the sheet that owns the slice by registration
index, or zero for a direct pivot.


```teal
tecs.gfx.animation.Pivot.sheet: number
```

<a id="tecs.gfx.animation.Pivot.slice"></a>
#### tecs.gfx.animation.Pivot.slice <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Selects the slice within that sheet by its
`Sheet:sliceId` index, or zero
for a pivot written directly.


```teal
tecs.gfx.animation.Pivot.slice: number
```

<a id="tecs.gfx.animation.Pivot.halfX"></a>
#### tecs.gfx.animation.Pivot.halfX <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Engine-owned. Stores half the horizontal range that the point may travel
over the current cycle, as a fraction of the frame.

A direct pivot or single-key slice uses zero, keeping the quad's exact
cull bound. A moving slice uses `x` and `y` for the travel midpoint and
this field for its reach on either side.


```teal
tecs.gfx.animation.Pivot.halfX: number
```

<a id="tecs.gfx.animation.Pivot.halfY"></a>
#### tecs.gfx.animation.Pivot.halfY <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Engine-owned. Stores the pivot's vertical travel for culling. Ordinary
game code should ignore this field.


```teal
tecs.gfx.animation.Pivot.halfY: number
```

<a id="tecs.gfx.animation.PlayOptions"></a>
### tecs.gfx.animation.PlayOptions <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Configures `of` and `play`.


```teal
record tecs.gfx.animation.PlayOptions
    speed: number
    loop: boolean
    playing: boolean
end
```

<a id="tecs.gfx.animation.PlayOptions.speed"></a>
#### tecs.gfx.animation.PlayOptions.speed <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Multiplies the sheet's own timing and defaults to one.


```teal
tecs.gfx.animation.PlayOptions.speed: number
```

<a id="tecs.gfx.animation.PlayOptions.loop"></a>
#### tecs.gfx.animation.PlayOptions.loop <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Controls whether the tag restarts after its last
frame. Defaults to true.


```teal
tecs.gfx.animation.PlayOptions.loop: boolean
```

<a id="tecs.gfx.animation.PlayOptions.playing"></a>
#### tecs.gfx.animation.PlayOptions.playing <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Controls whether playback starts immediately. Defaults
to true.


```teal
tecs.gfx.animation.PlayOptions.playing: boolean
```

<a id="tecs.gfx.animation.Rect"></a>
### tecs.gfx.animation.Rect <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

One frame, as `newRectSheet` and the builder take it.


```teal
record tecs.gfx.animation.Rect
    x: number
    y: number
    w: number
    h: number
    duration: number
end
```

<a id="tecs.gfx.animation.Rect.x"></a>
#### tecs.gfx.animation.Rect.x <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the frame's left edge in image pixels.


```teal
tecs.gfx.animation.Rect.x: number
```

<a id="tecs.gfx.animation.Rect.y"></a>
#### tecs.gfx.animation.Rect.y <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the frame's top edge in image pixels.


```teal
tecs.gfx.animation.Rect.y: number
```

<a id="tecs.gfx.animation.Rect.w"></a>
#### tecs.gfx.animation.Rect.w <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the frame width in pixels.


```teal
tecs.gfx.animation.Rect.w: number
```

<a id="tecs.gfx.animation.Rect.h"></a>
#### tecs.gfx.animation.Rect.h <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the frame height in pixels.


```teal
tecs.gfx.animation.Rect.h: number
```

<a id="tecs.gfx.animation.Rect.duration"></a>
#### tecs.gfx.animation.Rect.duration <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the frame duration in milliseconds and defaults
to `sheet.DEFAULT_DURATION`.


```teal
tecs.gfx.animation.Rect.duration: number
```

<a id="tecs.gfx.animation.RectsOptions"></a>
### tecs.gfx.animation.RectsOptions <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Configures `newRectSheet`.


```teal
record tecs.gfx.animation.RectsOptions
    name: string
    imageWidth: number
    imageHeight: number
    frames: {Rect}
    tags: {string: Tag}
    slices: {Slice}
end
```

<a id="tecs.gfx.animation.RectsOptions.name"></a>
#### tecs.gfx.animation.RectsOptions.name <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the required registration name.


```teal
tecs.gfx.animation.RectsOptions.name: string
```

<a id="tecs.gfx.animation.RectsOptions.imageWidth"></a>
#### tecs.gfx.animation.RectsOptions.imageWidth <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the required image width in pixels.


```teal
tecs.gfx.animation.RectsOptions.imageWidth: number
```

<a id="tecs.gfx.animation.RectsOptions.imageHeight"></a>
#### tecs.gfx.animation.RectsOptions.imageHeight <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the required image height in pixels.


```teal
tecs.gfx.animation.RectsOptions.imageHeight: number
```

<a id="tecs.gfx.animation.RectsOptions.frames"></a>
#### tecs.gfx.animation.RectsOptions.frames <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the required frame rects in address order.


```teal
tecs.gfx.animation.RectsOptions.frames: {Rect}
```

<a id="tecs.gfx.animation.RectsOptions.tags"></a>
#### tecs.gfx.animation.RectsOptions.tags <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Defines optional named tags over the frames.


```teal
tecs.gfx.animation.RectsOptions.tags: {string: Tag}
```

<a id="tecs.gfx.animation.RectsOptions.slices"></a>
#### tecs.gfx.animation.RectsOptions.slices <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Defines optional named slices.


```teal
tecs.gfx.animation.RectsOptions.slices: {Slice}
```

<a id="tecs.gfx.animation.Sheet"></a>
### tecs.gfx.animation.Sheet <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Read-only. Exposes an image divided into frames.


```teal
record tecs.gfx.animation.Sheet
    name: string
    id: integer
    count: integer
    imageWidth: number
    imageHeight: number

    bind: function(self, sprite: Sprite): Sheet
    cycle: function(self, id: integer): number
    duration: function(self, frame: integer): number
    frameAt: function(self, id: integer, time: number): integer
    hasTag: function(self, name: string): boolean
    pivot: function(self, name: string, frame: integer): Pivot
    pivotOf: function(self, id: integer, frame: integer): number, number
    rect: function(self, frame: integer): number, number, number, number
    slice: function(self, name: string): Slice
    sliceId: function(self, name: string): integer
    sliceKeyAt: function(self, id: integer, frame: integer): SliceKey
    sliceName: function(self, id: integer): string
    sprite: function(self, frame: integer): Sprite
    tag: function(self, name: string): integer, integer, Direction
    tagId: function(self, name: string): integer
    tagName: function(self, id: integer): string
    uv: function(self, frame: integer): number, number, number, number
end
```

<a id="tecs.gfx.animation.Sheet.name"></a>
#### tecs.gfx.animation.Sheet.name <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Reports the registered name that snapshots store.


```teal
tecs.gfx.animation.Sheet.name: string
```

<a id="tecs.gfx.animation.Sheet.id"></a>
#### tecs.gfx.animation.Sheet.id <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Reports the registration index carried by an
[`Animation`](/modules/gfx/animation/#tecs.gfx.animation.Animation). Construction assigns
an id once and never reuses it.


```teal
tecs.gfx.animation.Sheet.id: integer
```

<a id="tecs.gfx.animation.Sheet.count"></a>
#### tecs.gfx.animation.Sheet.count <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Reports the number of frames and the largest index `rect`, `uv` and `sprite`
accept.


```teal
tecs.gfx.animation.Sheet.count: integer
```

<a id="tecs.gfx.animation.Sheet.imageWidth"></a>
#### tecs.gfx.animation.Sheet.imageWidth <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Reports the source image width in pixels. Frame rectangles use
this width, so binding the sheet to an image of a different size places
frames incorrectly.


```teal
tecs.gfx.animation.Sheet.imageWidth: number
```

<a id="tecs.gfx.animation.Sheet.imageHeight"></a>
#### tecs.gfx.animation.Sheet.imageHeight <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Reports the height in pixels of the image from which frames
are cut.


```teal
tecs.gfx.animation.Sheet.imageHeight: number
```

<a id="tecs.gfx.animation.Sheet.bind"></a>
#### tecs.gfx.animation.Sheet:bind <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Resolves the sheet's frames against a registered image.

`sprite` is what `renderer.sprites:sprite(name)` returns for a whole image: its
`u1` and `v1` are the fractions of the texture-array layer that image
occupies. The function scales the frame's image fraction by them
before it names a region of the layer. Pass a sub-rect and the frames
land inside that sub-rect, which is not what the sheet describes.

Binding again rescales from the pixel rectangles instead of the previous
result, so re-registering an image does not accumulate scaling error.
Entities already carrying regions from an earlier bind keep them: a
rebind does not update any existing [`Sprite`](/modules/gfx/#tecs.gfx.Sprite).


```teal
function tecs.gfx.animation.Sheet.bind(self, sprite: Sprite): Sheet
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `sprite` | [`Sprite`](/modules/gfx/#tecs.gfx.Sprite) | A whole image, from `renderer.sprites:sprite`. |

##### Returns

| Type | Description |
| --- | --- |
| [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | Returns the sheet so callers can chain `bind`. |

<a id="tecs.gfx.animation.Sheet.cycle"></a>
#### tecs.gfx.animation.Sheet:cycle <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns the duration of one tag cycle in seconds.


```teal
function tecs.gfx.animation.Sheet.cycle(self, id: integer): number
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `id` | `integer` | A tag index, or zero for the whole sheet. |

##### Returns

| Type | Description |
| --- | --- |
| `number` | The sum of the durations of the frames the cycle visits, which for a pingpong tag counts the frames it passes twice twice. |

<a id="tecs.gfx.animation.Sheet.duration"></a>
#### tecs.gfx.animation.Sheet:duration <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns how long a frame remains visible, in seconds.


```teal
function tecs.gfx.animation.Sheet.duration(self, frame: integer): number
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `frame` | `integer` | One to `count`. Anything else raises. |

##### Returns

| Type | Description |
| --- | --- |
| `number` | Returns the authored frame duration in seconds. |

<a id="tecs.gfx.animation.Sheet.frameAt"></a>
#### tecs.gfx.animation.Sheet:frameAt <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns the frame shown by a tag at a point in its cycle.


```teal
function tecs.gfx.animation.Sheet.frameAt(
    self, id: integer, time: number
): integer
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `id` | `integer` | A tag index, or zero for the whole sheet. |
| `time` | `number` | Seconds into the cycle. Outside it clamps rather than wrapping, since wrapping is the caller's decision about looping. |

##### Returns

| Type | Description |
| --- | --- |
| `integer` | A frame index into the whole sheet, counting from one. |

<a id="tecs.gfx.animation.Sheet.hasTag"></a>
#### tecs.gfx.animation.Sheet:hasTag <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns whether the sheet contains the given tag.


```teal
function tecs.gfx.animation.Sheet.hasTag(self, name: string): boolean
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `name` | `string` | Any string, and nil answers false rather than raising, so this is what to ask before `tag`. |

##### Returns

| Type | Description |
| --- | --- |
| `boolean` | Whether `tag` would answer for that name. |

<a id="tecs.gfx.animation.Sheet.pivot"></a>
#### tecs.gfx.animation.Sheet:pivot <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Creates a Pivot from a named slice, ready to spawn.

Bound to the slice as well as resolved from it, so playback moves the
pivot as the frame changes rather than leaving it where the frame it
was built from put it.

Fails on a name the sheet does not carry, for the reason `tag` does:
the alternative is a typo that silently pivots on the middle.


```teal
function tecs.gfx.animation.Sheet.pivot(
    self, name: string, frame: integer
): Pivot
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `name` | `string` | A slice this sheet carries. |
| `frame` | `integer` | The frame to resolve it at, defaulting to the first. What an entity shows before its first step, and what a sheet with no Animation keeps. |

##### Returns

| Type | Description |
| --- | --- |
| [`Pivot`](/modules/gfx/animation/#tecs.gfx.animation.Pivot) | A component value, not an entity. |

<a id="tecs.gfx.animation.Sheet.pivotOf"></a>
#### tecs.gfx.animation.Sheet:pivotOf <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns a slice pivot as a fraction of its frame.

Aseprite writes a pivot in the slice's own pixels, so this adds the
slice's origin and divides by the frame, which is the number a quad
wants: nothing downstream has to know the sheet's pixel sizes.

A slice with a center but no pivot answers the center's middle, and a
slice with neither answers the middle of its own rectangle. Zero, a
slice the sheet does not carry, or a frame it has no key for all answer
the middle of the frame, which is where a quad sits with no pivot at
all.


```teal
function tecs.gfx.animation.Sheet.pivotOf(
    self, id: integer, frame: integer
): number, number
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `id` | `integer` | A slice index from `sliceId`. |
| `frame` | `integer` | A frame index. |

##### Returns

| Type | Description |
| --- | --- |
| `number` | The pivot's x and y as fractions of the frame, from its top left. |
| `number` |  |

<a id="tecs.gfx.animation.Sheet.rect"></a>
#### tecs.gfx.animation.Sheet:rect <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns a frame's pixel rectangle as x, y, width, and height.


```teal
function tecs.gfx.animation.Sheet.rect(
    self, frame: integer
): number, number, number, number
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `frame` | `integer` | One to `count`. Anything else raises, since a frame index out of range is a sheet and an animation disagreeing rather than something to paper over. |

##### Returns

| Type | Description |
| --- | --- |
| `number` | The rect's left, top, width and height, in the pixels of the image the sheet was cut from. |
| `number` |  |
| `number` |  |
| `number` |  |

<a id="tecs.gfx.animation.Sheet.slice"></a>
#### tecs.gfx.animation.Sheet:slice <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns a slice by name, or nil when the sheet does not contain one.


```teal
function tecs.gfx.animation.Sheet.slice(self, name: string): Slice
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `name` | `string` | A slice name. |

##### Returns

| Type | Description |
| --- | --- |
| [`Slice`](/modules/gfx/animation/#tecs.gfx.animation.Slice) | The slice, whose keys the caller must not mutate. |

<a id="tecs.gfx.animation.Sheet.sliceId"></a>
#### tecs.gfx.animation.Sheet:sliceId <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns the index represented by a slice name, or zero when absent.


```teal
function tecs.gfx.animation.Sheet.sliceId(self, name: string): integer
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `name` | `string` | A slice name, or nil. |

##### Returns

| Type | Description |
| --- | --- |
| `integer` | The index, which is what a component carries in place of the name for the reason a tag id is. |

<a id="tecs.gfx.animation.Sheet.sliceKeyAt"></a>
#### tecs.gfx.animation.Sheet:sliceKeyAt <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns the slice key active on a frame, or nil.

A slice holds a key until the next one, so this answers the last key at
or before the frame rather than only an exact match.


```teal
function tecs.gfx.animation.Sheet.sliceKeyAt(
    self, id: integer, frame: integer
): SliceKey
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `id` | `integer` | A slice index from `sliceId`. Zero answers nil. |
| `frame` | `integer` | A frame index. |

##### Returns

| Type | Description |
| --- | --- |
| [`SliceKey`](/modules/gfx/animation/#tecs.gfx.animation.SliceKey) |  |

<a id="tecs.gfx.animation.Sheet.sliceName"></a>
#### tecs.gfx.animation.Sheet:sliceName <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns the name represented by a slice index, or the empty string.



```teal
function tecs.gfx.animation.Sheet.sliceName(self, id: integer): string
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `id` | `integer` | A slice index from `sliceId`. Zero or an absent index returns the empty string. |

##### Returns

| Type | Description |
| --- | --- |
| `string` | The slice name, or the empty string when the index is absent. |

<a id="tecs.gfx.animation.Sheet.sprite"></a>
#### tecs.gfx.animation.Sheet:sprite <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Creates a Sprite showing one frame, ready to spawn.

Defaults to the first frame. Meaningful after `bind`, since before it
the sheet names no image and the quad has no layer to sample.


```teal
function tecs.gfx.animation.Sheet.sprite(self, frame: integer): Sprite
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `frame` | `integer` | One to `count`, defaulting to one. Anything else raises. |

##### Returns

| Type | Description |
| --- | --- |
| [`Sprite`](/modules/gfx/#tecs.gfx.Sprite) | Returns a fresh [`Sprite`](/modules/gfx/#tecs.gfx.Sprite) that the caller owns, not a view onto the sheet. |

<a id="tecs.gfx.animation.Sheet.tag"></a>
#### tecs.gfx.animation.Sheet:tag <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns the first frame, last frame, and direction of a named tag.

Fails on a name the sheet does not carry, because the alternative is an
animation silently playing the whole sheet on a typo.


```teal
function tecs.gfx.animation.Sheet.tag(
    self, name: string
): integer, integer, Direction
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `name` | `string` | A tag this sheet was built with. |

##### Returns

| Type | Description |
| --- | --- |
| `integer` | The tag's first frame index, its last, and its direction. |
| `integer` |  |
| [`Direction`](/modules/gfx/animation/#tecs.gfx.animation.Direction) |  |

<a id="tecs.gfx.animation.Sheet.tagId"></a>
#### tecs.gfx.animation.Sheet:tagId <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns the index represented by a tag name, or zero when absent.

Zero reads as the whole sheet rather than as nothing, so an animation
that names no tag plays every frame in order.

A name the sheet does not carry is reported at error level under the
`tecs.gfx` logger and then treated as the whole sheet. Zero is a
plausible wrong answer rather than a visible failure, so a misspelled
tag would otherwise animate every frame with nothing said. The report
names the sheet, the name asked for, and the tags the sheet does carry,
once per sheet and name however often the name is asked. Ask `hasTag`
instead when a name's absence is expected and ordinary.


```teal
function tecs.gfx.animation.Sheet.tagId(self, name: string): integer
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `name` | `string` | A tag name, or nil or the empty string for the whole sheet. The empty string is what a snapshot stores for tag zero, so neither it nor nil is reported. |

##### Returns

| Type | Description |
| --- | --- |
| `integer` | Returns the index an [`Animation`](/modules/gfx/animation/#tecs.gfx.animation.Animation) carries. The index belongs to this sheet alone: ids follow tag names in sorted order, so the same name in another sheet has another number. |

<a id="tecs.gfx.animation.Sheet.tagName"></a>
#### tecs.gfx.animation.Sheet:tagName <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns the name represented by a tag index, or the empty string for
the whole sheet.


```teal
function tecs.gfx.animation.Sheet.tagName(self, id: integer): string
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `id` | `integer` | An index from `tagId`. Nil, zero and anything the sheet does not carry all answer the empty string. |

##### Returns

| Type | Description |
| --- | --- |
| `string` | The tag's name, which is what a snapshot writes instead of the index. |

<a id="tecs.gfx.animation.Sheet.uv"></a>
#### tecs.gfx.animation.Sheet:uv <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns a frame's region as u0, v0, u1, and v1.

Fractions of the image before `bind` and of the texture-array layer
after it, which is the region a
[`Sprite`](/modules/gfx/#tecs.gfx.Sprite) needs.


```teal
function tecs.gfx.animation.Sheet.uv(
    self, frame: integer
): number, number, number, number
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Sheet` |  |
| `frame` | `integer` | One to `count`. Anything else raises. |

##### Returns

| Type | Description |
| --- | --- |
| `number` | The region's left, top, right and bottom edges. |
| `number` |  |
| `number` |  |
| `number` |  |

<a id="tecs.gfx.animation.Slice"></a>
### tecs.gfx.animation.Slice <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

A named region that moves across the frames.


```teal
record tecs.gfx.animation.Slice
    name: string
    data: string
    keys: {SliceKey}
end
```

<a id="tecs.gfx.animation.Slice.name"></a>
#### tecs.gfx.animation.Slice.name <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the name used to find the slice.


```teal
tecs.gfx.animation.Slice.name: string
```

<a id="tecs.gfx.animation.Slice.data"></a>
#### tecs.gfx.animation.Slice.data <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Stores free text carried by Aseprite.


```teal
tecs.gfx.animation.Slice.data: string
```

<a id="tecs.gfx.animation.Slice.keys"></a>
#### tecs.gfx.animation.Slice.keys <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets at least one key in frame order.


```teal
tecs.gfx.animation.Slice.keys: {SliceKey}
```

<a id="tecs.gfx.animation.SliceKey"></a>
### tecs.gfx.animation.SliceKey <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Defines where a slice sits from one frame onward.


```teal
record tecs.gfx.animation.SliceKey
    frame: integer
    x: number
    y: number
    w: number
    h: number
    centerX: number
    centerY: number
    centerW: number
    centerH: number
    pivotX: number
    pivotY: number
end
```

<a id="tecs.gfx.animation.SliceKey.frame"></a>
#### tecs.gfx.animation.SliceKey.frame <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the first frame on which this key takes effect,
counting from one.


```teal
tecs.gfx.animation.SliceKey.frame: integer
```

<a id="tecs.gfx.animation.SliceKey.x"></a>
#### tecs.gfx.animation.SliceKey.x <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the slice rectangle's left edge in frame pixels.


```teal
tecs.gfx.animation.SliceKey.x: number
```

<a id="tecs.gfx.animation.SliceKey.y"></a>
#### tecs.gfx.animation.SliceKey.y <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the slice rectangle's top edge in frame pixels.


```teal
tecs.gfx.animation.SliceKey.y: number
```

<a id="tecs.gfx.animation.SliceKey.w"></a>
#### tecs.gfx.animation.SliceKey.w <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the slice rectangle's width in pixels.


```teal
tecs.gfx.animation.SliceKey.w: number
```

<a id="tecs.gfx.animation.SliceKey.h"></a>
#### tecs.gfx.animation.SliceKey.h <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the slice rectangle's height in pixels.


```teal
tecs.gfx.animation.SliceKey.h: number
```

<a id="tecs.gfx.animation.SliceKey.centerX"></a>
#### tecs.gfx.animation.SliceKey.centerX <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the nine-slice center's left edge in slice
pixels. Nil means the slice has no center.


```teal
tecs.gfx.animation.SliceKey.centerX: number
```

<a id="tecs.gfx.animation.SliceKey.centerY"></a>
#### tecs.gfx.animation.SliceKey.centerY <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the nine-slice center's top edge in slice pixels.


```teal
tecs.gfx.animation.SliceKey.centerY: number
```

<a id="tecs.gfx.animation.SliceKey.centerW"></a>
#### tecs.gfx.animation.SliceKey.centerW <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the nine-slice center's width in pixels.


```teal
tecs.gfx.animation.SliceKey.centerW: number
```

<a id="tecs.gfx.animation.SliceKey.centerH"></a>
#### tecs.gfx.animation.SliceKey.centerH <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the nine-slice center's height in pixels.


```teal
tecs.gfx.animation.SliceKey.centerH: number
```

<a id="tecs.gfx.animation.SliceKey.pivotX"></a>
#### tecs.gfx.animation.SliceKey.pivotX <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the horizontal pivot in slice pixels. Nil means
the slice has no pivot.


```teal
tecs.gfx.animation.SliceKey.pivotX: number
```

<a id="tecs.gfx.animation.SliceKey.pivotY"></a>
#### tecs.gfx.animation.SliceKey.pivotY <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the vertical pivot in slice pixels. Nil means the
slice has no pivot.


```teal
tecs.gfx.animation.SliceKey.pivotY: number
```

<a id="tecs.gfx.animation.Tag"></a>
### tecs.gfx.animation.Tag <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

A named span of frames, as the constructors take it.


```teal
record tecs.gfx.animation.Tag
    from: integer
    to: integer
    direction: Direction
end
```

<a id="tecs.gfx.animation.Tag.from"></a>
#### tecs.gfx.animation.Tag.from <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the first frame index in the inclusive span.


```teal
tecs.gfx.animation.Tag.from: integer
```

<a id="tecs.gfx.animation.Tag.to"></a>
#### tecs.gfx.animation.Tag.to <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the last frame index in the inclusive span.


```teal
tecs.gfx.animation.Tag.to: integer
```

<a id="tecs.gfx.animation.Tag.direction"></a>
#### tecs.gfx.animation.Tag.direction <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the playback direction and defaults to
`"forward"`.


```teal
tecs.gfx.animation.Tag.direction: Direction
```

## Functions

<a id="tecs.gfx.animation.build"></a>
### tecs.gfx.animation.build <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates a builder for a sheet that the other constructors cannot
describe.

The model is what the builder writes, so an atlas from any tool reaches
the same sheet an Aseprite export does. Frames, tags and slices are
added in any order. `build` registers the finished sheet.


```teal
function tecs.gfx.animation.build(
    name: string, imageWidth: number, imageHeight: number
): Builder
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `name` | `string` | Name to register the finished sheet under. |
| `imageWidth` | `number` | Size of the image the frames are cut from, in pixels. |
| `imageHeight` | `number` |  |

#### Returns

| Type | Description |
| --- | --- |
| [`Builder`](/modules/gfx/animation/#tecs.gfx.animation.Builder) | A builder whose methods chain. |

<a id="tecs.gfx.animation.byId"></a>
### tecs.gfx.animation.byId <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Returns the sheet represented by a registration index, or nil.


```teal
function tecs.gfx.animation.byId(id: integer): Sheet
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `id` | `integer` | An `id` from a sheet this process built. Construction assigns ids in order, so each id is meaningful only within one run. |

#### Returns

| Type | Description |
| --- | --- |
| [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The sheet, or nil for an id nothing was built under. |

<a id="tecs.gfx.animation.byName"></a>
### tecs.gfx.animation.byName <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Returns the sheet registered under a name, or nil.

Building a second sheet under a name already taken replaces what this
returns, so a reload points new entities at the new sheet. Entities
already carrying the old id keep drawing the old one, which is what
stops a reload from pulling a frame out from under them.


```teal
function tecs.gfx.animation.byName(name: string): Sheet
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `name` | `string` | The name a sheet was built under. |

#### Returns

| Type | Description |
| --- | --- |
| [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The sheet most recently registered under that name, or nil. |

<a id="tecs.gfx.animation.findSheetById"></a>
### tecs.gfx.animation.findSheetById <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Returns the sheet represented by a process-wide id.


```teal
function tecs.gfx.animation.findSheetById(id: integer): sheet.Sheet
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `id` | `integer` | An id a constructor handed out. |

#### Returns

| Type | Description |
| --- | --- |
| [`sheet.Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The sheet, or nil when the id names none. |

<a id="tecs.gfx.animation.findSheetByName"></a>
### tecs.gfx.animation.findSheetByName <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Returns the sheet registered under a name.


```teal
function tecs.gfx.animation.findSheetByName(name: string): sheet.Sheet
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `name` | `string` | The name a constructor registered. |

#### Returns

| Type | Description |
| --- | --- |
| [`sheet.Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The sheet, or nil when the name names none. |

<a id="tecs.gfx.animation.frameOf"></a>
### tecs.gfx.animation.frameOf <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Returns the sheet frame shown by an entity's animation.

The same answer the vertex shader draws, because both are `frameAt` over
the same tag: the shader reads a table built from it and this calls it.
What a hitbox on frame five, a footstep on frame three or a muzzle on an
animated hand asks for.


```teal
function tecs.gfx.animation.frameOf(
    world: World, entity: integer
): integer
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `world` | [`World`](/modules/ecs/#tecs.World) | The world the entity lives in. |
| `entity` | `integer` | A live entity. |

#### Returns

| Type | Description |
| --- | --- |
| `integer` | A frame index into the whole sheet, counting from one, or zero for an entity with nothing to play. |

<a id="tecs.gfx.animation.fromAseprite"></a>
### tecs.gfx.animation.fromAseprite <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates a sheet from an Aseprite JSON export.

One reader in front of the model rather than a second model: frames,
their durations, frame tags with their directions, and slices with their
keys all land in the sheet the builder writes.

The reader accepts Aseprite's array layout and its object layout, sorting
the latter by frame name. It ignores `spriteSourceSize`, so export with
trimming off.


```teal
function tecs.gfx.animation.fromAseprite(
    options: AsepriteOptions
): Sheet
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `options` | [`AsepriteOptions`](/modules/gfx/animation/#tecs.gfx.animation.AsepriteOptions) | The export and the name to register it under. |

#### Returns

| Type | Description |
| --- | --- |
| [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The finished sheet. |

<a id="tecs.gfx.animation.grid"></a>
### tecs.gfx.animation.grid <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates a sheet whose frames form a uniform grid.

Margin surrounds the grid and spacing separates the cells, so a cell's
left edge is `margin + column * (frameWidth + spacing)`. Both default to
zero, which is an image cut with nothing between its cells.


```teal
function tecs.gfx.animation.grid(options: GridOptions): Sheet
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `options` | [`GridOptions`](/modules/gfx/animation/#tecs.gfx.animation.GridOptions) | Raises on a missing name, a non-positive image or frame size, a grid that fits no cells, or a `count` past what the grid holds. Frames come out in row-major order. |

#### Returns

| Type | Description |
| --- | --- |
| [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The finished sheet, already registered under its name and carrying an `id`. |

<a id="tecs.gfx.animation.of"></a>
### tecs.gfx.animation.of <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates an [`Animation`](/modules/gfx/animation/#tecs.gfx.animation.Animation) that
plays a named sheet tag and is ready to spawn.

Omit the tag to play the whole sheet in order. Fails on a tag the sheet
does not carry, since the alternative is a typo that plays every
frame.

The entity also needs a [`Sprite`](/modules/gfx/#tecs.gfx.Sprite),
which the query matches and playback writes what is playing into. An
[`Animation`](/modules/gfx/animation/#tecs.gfx.animation.Animation) on its own draws
nothing.


```teal
function tecs.gfx.animation.of(
    source: Sheet, tag: string, options: PlayOptions
): Animation
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `source` | [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The sheet to play. Nil raises. |
| `tag` | `string` | A tag the sheet names, or nil for the whole sheet. A name the sheet does not carry raises here rather than reporting and playing the whole sheet, because an author naming a tag at this call has one in mind and the sheet is already in hand to check against. |
| `options` | [`PlayOptions`](/modules/gfx/animation/#tecs.gfx.animation.PlayOptions) | Defaults are the sheet's own timing, looping, and playing. |

#### Returns

| Type | Description |
| --- | --- |
| [`Animation`](/modules/gfx/animation/#tecs.gfx.animation.Animation) | A component value, not an entity: pass it to `world:spawn` or `world:set` yourself. |

<a id="tecs.gfx.animation.play"></a>
### tecs.gfx.animation.play <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Points a live entity at a tag and restarts it there.

Restarting is the point: time and frame both reset, so the next step
writes the tag's first frame whatever the entity was showing. An entity
carrying no Animation gets one.


```teal
function tecs.gfx.animation.play(
    world: World,
    entity: integer,
    source: Sheet,
    tag: string,
    options: PlayOptions
)
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `world` | [`World`](/modules/ecs/#tecs.World) | The world the entity lives in. |
| `entity` | `integer` | A live entity with a [`Sprite`](/modules/gfx/#tecs.gfx.Sprite). |
| `source` | [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The sheet to play. Nil raises. |
| `tag` | `string` | A tag the sheet names, or nil for the whole sheet. A name the sheet does not carry raises, as it does in `of`. |
| `options` | [`PlayOptions`](/modules/gfx/animation/#tecs.gfx.animation.PlayOptions) | Defaults are the sheet's own timing, looping, and playing. |

#### Returns

None.

<a id="tecs.gfx.animation.plugin"></a>
### tecs.gfx.animation.plugin <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Adds the systems that drive playback.

Call this once for each world that plays sprite sheets. A second call on
the same world does nothing.

It installs three systems, all in `PostUpdate` so they land before
extraction whatever order a game added its plugins in.
`tecs.EncodeAnimation` writes what each entity is playing into its
[`Sprite`](/modules/gfx/#tecs.gfx.Sprite) and writes nothing on a step
where nothing changed what is playing. `tecs.ReportAnimation` derives
[`Completed`](/modules/gfx/animation/#tecs.gfx.animation.Completed) and
[`Looped`](/modules/gfx/animation/#tecs.gfx.animation.Looped) for entities carrying
[`AnimationEvents`](/modules/gfx/animation/#tecs.gfx.animation.AnimationEvents).
`tecs.RebaseAnimation` moves the playback clock's origin every few hours
of uptime and re-anchors every animated row on it, which is the one
update in a hundred thousand that writes every playing animation.


```teal
function tecs.gfx.animation.plugin(world: World)
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `world` | [`World`](/modules/ecs/#tecs.World) | The world to add the systems to. |

#### Returns

None.

<a id="tecs.gfx.animation.rects"></a>
### tecs.gfx.animation.rects <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates a sheet from explicitly listed frame rectangles.

For an image no grid describes: frames of differing sizes, or an atlas
whose cells a packing tool placed.


```teal
function tecs.gfx.animation.rects(options: RectsOptions): Sheet
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `options` | [`RectsOptions`](/modules/gfx/animation/#tecs.gfx.animation.RectsOptions) | Raises on a missing name, a non-positive image size, an empty frame list, or a frame with no positive size. Rects are not checked against the image, so one that runs off the edge samples whatever the layer holds there. |

#### Returns

| Type | Description |
| --- | --- |
| [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | The finished sheet, already registered under its name and carrying an `id`. |

<a id="tecs.gfx.animation.replace"></a>
### tecs.gfx.animation.replace <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Folds a re-exported sheet into the one already registered under its
name, in place, so an entity playing the old id shows the new frames.


```teal
function tecs.gfx.animation.replace(
    built: sheet.Sheet
): sheet.Sheet, string
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `built` | [`sheet.Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | A sheet from any constructor here, registered moments ago under a name something else already holds. |

#### Returns

| Type | Description |
| --- | --- |
| [`sheet.Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | Returns the live sheet and nil, or nil and the refusal reason. |
| `string` |  |

<a id="tecs.gfx.animation.restart"></a>
### tecs.gfx.animation.restart <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Plays an entity's animation again from the start of its tag.

The sheet, tag, speed and loop flag are left as they are; what resets
is where in the cycle playback has got to and whether it is running. For
replaying a one-shot that has finished, and for rewinding one that has
not.


```teal
function tecs.gfx.animation.restart(
    world: World, entity: integer
): boolean
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `world` | [`World`](/modules/ecs/#tecs.World) | The world the entity lives in. |
| `entity` | `integer` | A live entity. |

#### Returns

| Type | Description |
| --- | --- |
| `boolean` | Whether there was an Animation to restart. False leaves the entity untouched, since there is nothing to say what it would play. |

<a id="tecs.gfx.animation.revision"></a>
### tecs.gfx.animation.revision <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Returns how many times any sheet's frames have changed.

Bumped by registration and by `bind`, both of which move where a frame's
region points. Anything holding a copy of those regions compares this
against what it copied from rather than being told, which keeps the
dependency running one way: a sheet knows nothing about who read it.


```teal
function tecs.gfx.animation.revision(): integer
```

#### Arguments

None.

#### Returns

| Type | Description |
| --- | --- |
| `integer` | A number that only ever increases. |

<a id="tecs.gfx.animation.sheetRevision"></a>
### tecs.gfx.animation.sheetRevision <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Returns how many times any sheet's frames have changed.

What a cache of anything derived from a sheet compares against, so a
sheet replaced or rebound under a running game invalidates it.


```teal
function tecs.gfx.animation.sheetRevision(): integer
```

#### Arguments

None.

#### Returns

| Type | Description |
| --- | --- |
| `integer` | A number that only ever increases. |

<a id="tecs.gfx.animation.timeOf"></a>
### tecs.gfx.animation.timeOf <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Returns an animation's position in its tag cycle, in seconds.

Recomputed on the call rather than kept in a column, because keeping it
means writing every animating entity on every step and that is the cost
resolving the frame in the shader exists to remove. A few hundred calls a step is free; it
stops being free somewhere in the tens of thousands, which is a game
asking a question this is the wrong shape for.


```teal
function tecs.gfx.animation.timeOf(
    world: World, entity: integer
): number
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `world` | [`World`](/modules/ecs/#tecs.World) | The world the entity lives in. |
| `entity` | `integer` | A live entity. |

#### Returns

| Type | Description |
| --- | --- |
| `number` | Seconds into the cycle, wrapped for a looping tag and clamped at the end for a one-shot. Zero for an entity carrying no Animation and for one whose sheet this run does not have. |

## Values

<a id="tecs.gfx.animation.DEFAULT_DURATION"></a>
### tecs.gfx.animation.DEFAULT_DURATION <span class="tealdoc-kind-badge tealdoc-kind-variable">variable</span>

Read-only. Reports how many milliseconds a frame remains visible when
nothing overrides its duration.


```teal
tecs.gfx.animation.DEFAULT_DURATION: number
```