On this page
  1. tecs.gfx.animation
  2. Sheet sources
  3. Slices and pivots
  4. Reloads
  5. Module contents
    1. Constructors
    2. Types
    3. Functions
    4. Values
  6. Constructors
    1. newGridSheet
    2. newRectSheet
    3. newSheetBuilder
    4. newSheetFromAseprite
  7. Types
    1. Animation
    2. AnimationEvents
    3. AsepriteOptions
    4. Builder
    5. Completed
    6. Direction
    7. GridOptions
    8. Looped
    9. Pivot
    10. PlayOptions
    11. Rect
    12. RectsOptions
    13. Sheet
    14. Slice
    15. SliceKey
    16. Tag
  8. Functions
    1. build
    2. byId
    3. byName
    4. findSheetById
    5. findSheetByName
    6. frameOf
    7. fromAseprite
    8. grid
    9. of
    10. play
    11. plugin
    12. rects
    13. replace
    14. restart
    15. revision
    16. sheetRevision
    17. timeOf
  9. Values
    1. DEFAULT_DURATION

tecs.gfx.animation

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

A Sheet divides one image into frames and names frame ranges with tags. An Animation selects a sheet tag and carries speed, loop, and playback state.

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 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:

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 for one frame. pivot(name, frame) creates a 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 Creates a sheet whose frames form a uniform grid.
newRectSheet Creates a sheet from explicitly listed frame rectangles.
newSheetBuilder Creates a builder for a sheet that the other constructors cannot describe.
newSheetFromAseprite Creates a sheet from an Aseprite JSON export.

Types

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

Functions

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

Values

Value Type Description
DEFAULT_DURATION number Read-only. Reports how many milliseconds a frame remains visible when nothing overrides its duration.

Constructors

tecs.gfx.animation.newGridSheet Static

Creates a sheet whose frames form a uniform grid.

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

Arguments

Name Type Description
options sheet.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 The finished sheet, already registered under its name and carrying an id.

tecs.gfx.animation.newRectSheet Static

Creates a sheet from explicitly listed frame rectangles.

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

Arguments

Name Type Description
options sheet.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 The finished sheet, already registered under its name and carrying an id.

tecs.gfx.animation.newSheetBuilder Static

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

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 Returns a builder that registers the sheet when finish runs.

tecs.gfx.animation.newSheetFromAseprite Static

Creates a sheet from an Aseprite JSON export.

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

Arguments

Name Type Description
options sheet.AsepriteOptions Raises on a missing name or an export the reader cannot make a sheet out of.

Returns

Type Description
sheet.Sheet The finished sheet, already registered.

Types

tecs.gfx.animation.Animation record

Stores playback state for one entity.

What an entity is playing lives here and where its cycle has got to lives in its Sprite, which carries the playback the shader resolves. So frame is not an index: the encoder writes ENCODED to say the 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.

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

tecs.gfx.animation.Animation.sheet field

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

tecs.gfx.animation.Animation.sheet: number

tecs.gfx.animation.Animation.tag field

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

tecs.gfx.animation.Animation.tag: number

tecs.gfx.animation.Animation.speed field

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.

tecs.gfx.animation.Animation.speed: number

tecs.gfx.animation.Animation.time field

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.

tecs.gfx.animation.Animation.time: number

tecs.gfx.animation.Animation.frame field

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.

tecs.gfx.animation.Animation.frame: number

tecs.gfx.animation.Animation.loop field

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

tecs.gfx.animation.Animation.loop: boolean

tecs.gfx.animation.Animation.playing field

Caller-writable. Controls whether time advances.

tecs.gfx.animation.Animation.playing: boolean

tecs.gfx.animation.AnimationEvents record

Requests Completed and 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 and Looped events for an entity.

record tecs.gfx.animation.AnimationEvents is Component
end

Interfaces

Interface
Component

tecs.gfx.animation.AsepriteOptions record

Configures newSheetFromAseprite.

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

tecs.gfx.animation.AsepriteOptions.name field

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

tecs.gfx.animation.AsepriteOptions.name: string

tecs.gfx.animation.AsepriteOptions.json field

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.

tecs.gfx.animation.AsepriteOptions.json: any

tecs.gfx.animation.Builder record

Builds custom sheets one frame at a time.

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

tecs.gfx.animation.Builder:finish Instance

Registers and returns the finished sheet.

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

function tecs.gfx.animation.Builder.finish(self): Sheet
Arguments
Name Type Description
self Builder
Returns
Type Description
Sheet

tecs.gfx.animation.Builder:frame Instance

Appends a frame to the sheet under construction.

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 The builder.

tecs.gfx.animation.Builder:slice Instance

Adds a fixed slice with a pivot.

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 The builder.

tecs.gfx.animation.Builder:sliceKeys Instance

Adds a slice from explicit keys for importers.

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} Keys in frame order, at least one.
Returns
Type Description
Builder The builder.

tecs.gfx.animation.Builder:tag Instance

Names an inclusive frame span and its playback direction.

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 Defaults to "forward".
Returns
Type Description
Builder The builder.

tecs.gfx.animation.Completed record

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.

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

tecs.gfx.animation.Completed.entity field

Read-only. Identifies the entity whose animation completed.

tecs.gfx.animation.Completed.entity: integer

tecs.gfx.animation.Completed.sheet field

Read-only. Reports the sheet that completed.

tecs.gfx.animation.Completed.sheet: Sheet

tecs.gfx.animation.Completed.tag field

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

tecs.gfx.animation.Completed.tag: string

tecs.gfx.animation.Completed:__call metamethod

Creates a completed event value.

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 The sheet that completed.
tag string The tag that completed, or an empty string for the whole sheet.
Returns
Type Description
Completed The completed event value.

tecs.gfx.animation.Direction enum

Selects how a tag walks its span.

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

tecs.gfx.animation.GridOptions record

Configures newGridSheet.

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

tecs.gfx.animation.GridOptions.name field

Caller-writable. Sets the required registration name.

tecs.gfx.animation.GridOptions.name: string

tecs.gfx.animation.GridOptions.imageWidth field

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

tecs.gfx.animation.GridOptions.imageWidth: number

tecs.gfx.animation.GridOptions.imageHeight field

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

tecs.gfx.animation.GridOptions.imageHeight: number

tecs.gfx.animation.GridOptions.frameWidth field

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

tecs.gfx.animation.GridOptions.frameWidth: number

tecs.gfx.animation.GridOptions.frameHeight field

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

tecs.gfx.animation.GridOptions.frameHeight: number

tecs.gfx.animation.GridOptions.margin field

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

tecs.gfx.animation.GridOptions.margin: number

tecs.gfx.animation.GridOptions.spacing field

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

tecs.gfx.animation.GridOptions.spacing: number

tecs.gfx.animation.GridOptions.columns field

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

tecs.gfx.animation.GridOptions.columns: integer

tecs.gfx.animation.GridOptions.rows field

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

tecs.gfx.animation.GridOptions.rows: integer

tecs.gfx.animation.GridOptions.count field

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.

tecs.gfx.animation.GridOptions.count: integer

tecs.gfx.animation.GridOptions.duration field

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.

tecs.gfx.animation.GridOptions.duration: number

tecs.gfx.animation.GridOptions.tags field

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

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

tecs.gfx.animation.GridOptions.slices field

Caller-writable. Defines optional named slices.

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

tecs.gfx.animation.Looped record

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.

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

tecs.gfx.animation.Looped.entity field

Read-only. Identifies the entity whose animation looped.

tecs.gfx.animation.Looped.entity: integer

tecs.gfx.animation.Looped.sheet field

Read-only. Reports the sheet that looped.

tecs.gfx.animation.Looped.sheet: Sheet

tecs.gfx.animation.Looped.tag field

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

tecs.gfx.animation.Looped.tag: string

tecs.gfx.animation.Looped:__call metamethod

Creates a looped event value.

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 The sheet that looped.
tag string The tag that looped, or an empty string for the whole sheet.
Returns
Type Description
Looped The looped event value.

tecs.gfx.animation.Pivot record

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

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

Interfaces

Interface
Component

tecs.gfx.animation.Pivot.x field

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

tecs.gfx.animation.Pivot.x: number

tecs.gfx.animation.Pivot.y field

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

tecs.gfx.animation.Pivot.y: number

tecs.gfx.animation.Pivot.sheet field

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

tecs.gfx.animation.Pivot.sheet: number

tecs.gfx.animation.Pivot.slice field

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

tecs.gfx.animation.Pivot.slice: number

tecs.gfx.animation.Pivot.halfX field

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.

tecs.gfx.animation.Pivot.halfX: number

tecs.gfx.animation.Pivot.halfY field

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

tecs.gfx.animation.Pivot.halfY: number

tecs.gfx.animation.PlayOptions record

Configures of and play.

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

tecs.gfx.animation.PlayOptions.speed field

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

tecs.gfx.animation.PlayOptions.speed: number

tecs.gfx.animation.PlayOptions.loop field

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

tecs.gfx.animation.PlayOptions.loop: boolean

tecs.gfx.animation.PlayOptions.playing field

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

tecs.gfx.animation.PlayOptions.playing: boolean

tecs.gfx.animation.Rect record

One frame, as newRectSheet and the builder take it.

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

tecs.gfx.animation.Rect.x field

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

tecs.gfx.animation.Rect.x: number

tecs.gfx.animation.Rect.y field

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

tecs.gfx.animation.Rect.y: number

tecs.gfx.animation.Rect.w field

Caller-writable. Sets the frame width in pixels.

tecs.gfx.animation.Rect.w: number

tecs.gfx.animation.Rect.h field

Caller-writable. Sets the frame height in pixels.

tecs.gfx.animation.Rect.h: number

tecs.gfx.animation.Rect.duration field

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

tecs.gfx.animation.Rect.duration: number

tecs.gfx.animation.RectsOptions record

Configures newRectSheet.

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

tecs.gfx.animation.RectsOptions.name field

Caller-writable. Sets the required registration name.

tecs.gfx.animation.RectsOptions.name: string

tecs.gfx.animation.RectsOptions.imageWidth field

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

tecs.gfx.animation.RectsOptions.imageWidth: number

tecs.gfx.animation.RectsOptions.imageHeight field

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

tecs.gfx.animation.RectsOptions.imageHeight: number

tecs.gfx.animation.RectsOptions.frames field

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

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

tecs.gfx.animation.RectsOptions.tags field

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

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

tecs.gfx.animation.RectsOptions.slices field

Caller-writable. Defines optional named slices.

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

tecs.gfx.animation.Sheet record

Read-only. Exposes an image divided into frames.

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

tecs.gfx.animation.Sheet.name field

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

tecs.gfx.animation.Sheet.name: string

tecs.gfx.animation.Sheet.id field

Read-only. Reports the registration index carried by an Animation. Construction assigns an id once and never reuses it.

tecs.gfx.animation.Sheet.id: integer

tecs.gfx.animation.Sheet.count field

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

tecs.gfx.animation.Sheet.count: integer

tecs.gfx.animation.Sheet.imageWidth field

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.

tecs.gfx.animation.Sheet.imageWidth: number

tecs.gfx.animation.Sheet.imageHeight field

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

tecs.gfx.animation.Sheet.imageHeight: number

tecs.gfx.animation.Sheet:bind Instance

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.

function tecs.gfx.animation.Sheet.bind(self, sprite: Sprite): Sheet
Arguments
Name Type Description
self Sheet
sprite Sprite A whole image, from renderer.sprites:sprite.
Returns
Type Description
Sheet Returns the sheet so callers can chain bind.

tecs.gfx.animation.Sheet:cycle Instance

Returns the duration of one tag cycle in seconds.

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.

tecs.gfx.animation.Sheet:duration Instance

Returns how long a frame remains visible, in seconds.

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.

tecs.gfx.animation.Sheet:frameAt Instance

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

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.

tecs.gfx.animation.Sheet:hasTag Instance

Returns whether the sheet contains the given tag.

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.

tecs.gfx.animation.Sheet:pivot Instance

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.

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 A component value, not an entity.

tecs.gfx.animation.Sheet:pivotOf Instance

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.

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

tecs.gfx.animation.Sheet:rect Instance

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

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

tecs.gfx.animation.Sheet:slice Instance

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

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 The slice, whose keys the caller must not mutate.

tecs.gfx.animation.Sheet:sliceId Instance

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

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.

tecs.gfx.animation.Sheet:sliceKeyAt Instance

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.

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

tecs.gfx.animation.Sheet:sliceName Instance

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

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.

tecs.gfx.animation.Sheet:sprite Instance

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.

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 Returns a fresh Sprite that the caller owns, not a view onto the sheet.

tecs.gfx.animation.Sheet:tag Instance

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.

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

tecs.gfx.animation.Sheet:tagId Instance

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.

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 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.

tecs.gfx.animation.Sheet:tagName Instance

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

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.

tecs.gfx.animation.Sheet:uv Instance

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 needs.

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

tecs.gfx.animation.Slice record

A named region that moves across the frames.

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

tecs.gfx.animation.Slice.name field

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

tecs.gfx.animation.Slice.name: string

tecs.gfx.animation.Slice.data field

Caller-writable. Stores free text carried by Aseprite.

tecs.gfx.animation.Slice.data: string

tecs.gfx.animation.Slice.keys field

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

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

tecs.gfx.animation.SliceKey record

Defines where a slice sits from one frame onward.

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

tecs.gfx.animation.SliceKey.frame field

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

tecs.gfx.animation.SliceKey.frame: integer

tecs.gfx.animation.SliceKey.x field

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

tecs.gfx.animation.SliceKey.x: number

tecs.gfx.animation.SliceKey.y field

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

tecs.gfx.animation.SliceKey.y: number

tecs.gfx.animation.SliceKey.w field

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

tecs.gfx.animation.SliceKey.w: number

tecs.gfx.animation.SliceKey.h field

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

tecs.gfx.animation.SliceKey.h: number

tecs.gfx.animation.SliceKey.centerX field

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

tecs.gfx.animation.SliceKey.centerX: number

tecs.gfx.animation.SliceKey.centerY field

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

tecs.gfx.animation.SliceKey.centerY: number

tecs.gfx.animation.SliceKey.centerW field

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

tecs.gfx.animation.SliceKey.centerW: number

tecs.gfx.animation.SliceKey.centerH field

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

tecs.gfx.animation.SliceKey.centerH: number

tecs.gfx.animation.SliceKey.pivotX field

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

tecs.gfx.animation.SliceKey.pivotX: number

tecs.gfx.animation.SliceKey.pivotY field

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

tecs.gfx.animation.SliceKey.pivotY: number

tecs.gfx.animation.Tag record

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

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

tecs.gfx.animation.Tag.from field

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

tecs.gfx.animation.Tag.from: integer

tecs.gfx.animation.Tag.to field

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

tecs.gfx.animation.Tag.to: integer

tecs.gfx.animation.Tag.direction field

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

tecs.gfx.animation.Tag.direction: Direction

Functions

tecs.gfx.animation.build Static

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.

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 A builder whose methods chain.

tecs.gfx.animation.byId Static

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

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 The sheet, or nil for an id nothing was built under.

tecs.gfx.animation.byName Static

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.

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 The sheet most recently registered under that name, or nil.

tecs.gfx.animation.findSheetById Static

Returns the sheet represented by a process-wide id.

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 The sheet, or nil when the id names none.

tecs.gfx.animation.findSheetByName Static

Returns the sheet registered under a name.

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 The sheet, or nil when the name names none.

tecs.gfx.animation.frameOf Static

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.

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

Arguments

Name Type Description
world 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.

tecs.gfx.animation.fromAseprite Static

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.

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

Arguments

Name Type Description
options AsepriteOptions The export and the name to register it under.

Returns

Type Description
Sheet The finished sheet.

tecs.gfx.animation.grid Static

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.

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

Arguments

Name Type Description
options 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 The finished sheet, already registered under its name and carrying an id.

tecs.gfx.animation.of Static

Creates an 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, which the query matches and playback writes what is playing into. An Animation on its own draws nothing.

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

Arguments

Name Type Description
source 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 Defaults are the sheet's own timing, looping, and playing.

Returns

Type Description
Animation A component value, not an entity: pass it to world:spawn or world:set yourself.

tecs.gfx.animation.play Static

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.

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

Arguments

Name Type Description
world World The world the entity lives in.
entity integer A live entity with a Sprite.
source 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 Defaults are the sheet's own timing, looping, and playing.

Returns

None.

tecs.gfx.animation.plugin Static

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 and writes nothing on a step where nothing changed what is playing. tecs.ReportAnimation derives Completed and Looped for entities carrying 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.

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

Arguments

Name Type Description
world World The world to add the systems to.

Returns

None.

tecs.gfx.animation.rects Static

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.

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

Arguments

Name Type Description
options 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 The finished sheet, already registered under its name and carrying an id.

tecs.gfx.animation.replace Static

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.

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

Arguments

Name Type Description
built sheet.Sheet A sheet from any constructor here, registered moments ago under a name something else already holds.

Returns

Type Description
sheet.Sheet Returns the live sheet and nil, or nil and the refusal reason.
string

tecs.gfx.animation.restart Static

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.

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

Arguments

Name Type Description
world 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.

tecs.gfx.animation.revision Static

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.

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

Arguments

None.

Returns

Type Description
integer A number that only ever increases.

tecs.gfx.animation.sheetRevision Static

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.

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

Arguments

None.

Returns

Type Description
integer A number that only ever increases.

tecs.gfx.animation.timeOf Static

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.

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

Arguments

Name Type Description
world 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

tecs.gfx.animation.DEFAULT_DURATION variable

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

tecs.gfx.animation.DEFAULT_DURATION: number