# 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 = 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 = 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) | record | Stores playback state for one entity. | | [`AnimationEvents`](/modules/gfx/animation/#tecs.gfx.animation.AnimationEvents) | record | Requests Completed and Looped events for an entity. | | [`AsepriteOptions`](/modules/gfx/animation/#tecs.gfx.animation.AsepriteOptions) | record | Configures newSheetFromAseprite. | | [`Builder`](/modules/gfx/animation/#tecs.gfx.animation.Builder) | record | Builds custom sheets one frame at a time. | | [`Completed`](/modules/gfx/animation/#tecs.gfx.animation.Completed) | record | Reports when a non-looping tag runs past its last frame. | | [`Direction`](/modules/gfx/animation/#tecs.gfx.animation.Direction) | enum | Selects how a tag walks its span. | | [`GridOptions`](/modules/gfx/animation/#tecs.gfx.animation.GridOptions) | record | Configures newGridSheet. | | [`Looped`](/modules/gfx/animation/#tecs.gfx.animation.Looped) | record | Reports when a looping tag passes its last frame and restarts. | | [`Pivot`](/modules/gfx/animation/#tecs.gfx.animation.Pivot) | record | Read-only. Exposes the pivot component that controls where an entity's quad turns and scales. | | [`PlayOptions`](/modules/gfx/animation/#tecs.gfx.animation.PlayOptions) | record | Configures of and play. | | [`Rect`](/modules/gfx/animation/#tecs.gfx.animation.Rect) | record | One frame, as newRectSheet and the builder take it. | | [`RectsOptions`](/modules/gfx/animation/#tecs.gfx.animation.RectsOptions) | record | Configures newRectSheet. | | [`Sheet`](/modules/gfx/animation/#tecs.gfx.animation.Sheet) | record | Read-only. Exposes an image divided into frames. | | [`Slice`](/modules/gfx/animation/#tecs.gfx.animation.Slice) | record | A named region that moves across the frames. | | [`SliceKey`](/modules/gfx/animation/#tecs.gfx.animation.SliceKey) | record | Defines where a slice sits from one frame onward. | | [`Tag`](/modules/gfx/animation/#tecs.gfx.animation.Tag) | record | A named span of frames, as the constructors take it. | ### Functions | Function | Kind | Description | | --- | --- | --- | | [`build`](/modules/gfx/animation/#tecs.gfx.animation.build) | Static | Creates a builder for a sheet that the other constructors cannot describe. | | [`byId`](/modules/gfx/animation/#tecs.gfx.animation.byId) | Static | Returns the sheet represented by a registration index, or nil. | | [`byName`](/modules/gfx/animation/#tecs.gfx.animation.byName) | Static | Returns the sheet registered under a name, or nil. | | [`findSheetById`](/modules/gfx/animation/#tecs.gfx.animation.findSheetById) | Static | Returns the sheet represented by a process-wide id. | | [`findSheetByName`](/modules/gfx/animation/#tecs.gfx.animation.findSheetByName) | Static | Returns the sheet registered under a name. | | [`frameOf`](/modules/gfx/animation/#tecs.gfx.animation.frameOf) | Static | Returns the sheet frame shown by an entity's animation. | | [`fromAseprite`](/modules/gfx/animation/#tecs.gfx.animation.fromAseprite) | Static | Creates a sheet from an Aseprite JSON export. | | [`grid`](/modules/gfx/animation/#tecs.gfx.animation.grid) | Static | Creates a sheet whose frames form a uniform grid. | | [`of`](/modules/gfx/animation/#tecs.gfx.animation.of) | Static | Creates an Animation that plays a named sheet tag and is ready to spawn. | | [`play`](/modules/gfx/animation/#tecs.gfx.animation.play) | Static | Points a live entity at a tag and restarts it there. | | [`plugin`](/modules/gfx/animation/#tecs.gfx.animation.plugin) | Static | Adds the systems that drive playback. | | [`rects`](/modules/gfx/animation/#tecs.gfx.animation.rects) | Static | Creates a sheet from explicitly listed frame rectangles. | | [`replace`](/modules/gfx/animation/#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... | | [`restart`](/modules/gfx/animation/#tecs.gfx.animation.restart) | Static | Plays an entity's animation again from the start of its tag. | | [`revision`](/modules/gfx/animation/#tecs.gfx.animation.revision) | Static | Returns how many times any sheet's frames have changed. | | [`sheetRevision`](/modules/gfx/animation/#tecs.gfx.animation.sheetRevision) | Static | Returns how many times any sheet's frames have changed. | | [`timeOf`](/modules/gfx/animation/#tecs.gfx.animation.timeOf) | Static | 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 ### tecs.gfx.animation.newGridSheet Static 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`. | ### tecs.gfx.animation.newRectSheet Static 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`. | ### tecs.gfx.animation.newSheetBuilder Static 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. | ### tecs.gfx.animation.newSheetFromAseprite Static 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 ### 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`](/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) | #### tecs.gfx.animation.Animation.sheet field Caller-writable. Selects a sheet by its `Sheet.id` registration index. Zero plays nothing. ```teal 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. ```teal 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. ```teal 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. ```teal 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. ```teal tecs.gfx.animation.Animation.frame: number ``` #### tecs.gfx.animation.Animation.loop field Caller-writable. Controls whether the tag restarts after its last frame. ```teal tecs.gfx.animation.Animation.loop: boolean ``` #### tecs.gfx.animation.Animation.playing field Caller-writable. Controls whether time advances. ```teal tecs.gfx.animation.Animation.playing: boolean ``` ### tecs.gfx.animation.AnimationEvents record 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) | ### tecs.gfx.animation.AsepriteOptions record Configures `newSheetFromAseprite`. ```teal 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. ```teal 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. ```teal tecs.gfx.animation.AsepriteOptions.json: any ``` ### tecs.gfx.animation.Builder record 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 ``` #### 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. ```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) | | #### tecs.gfx.animation.Builder:frame Instance 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. | #### tecs.gfx.animation.Builder:slice Instance 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. | #### tecs.gfx.animation.Builder:sliceKeys Instance 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. | #### tecs.gfx.animation.Builder:tag Instance 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. | ### 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. ```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) | #### tecs.gfx.animation.Completed.entity field Read-only. Identifies the entity whose animation completed. ```teal tecs.gfx.animation.Completed.entity: integer ``` #### tecs.gfx.animation.Completed.sheet field Read-only. Reports the sheet that completed. ```teal 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. ```teal tecs.gfx.animation.Completed.tag: string ``` #### tecs.gfx.animation.Completed:__call metamethod 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. | ### tecs.gfx.animation.Direction enum Selects how a tag walks its span. ```teal enum tecs.gfx.animation.Direction "forward" "pingpong" "reverse" end ``` ### tecs.gfx.animation.GridOptions record 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 ``` #### tecs.gfx.animation.GridOptions.name field Caller-writable. Sets the required registration name. ```teal tecs.gfx.animation.GridOptions.name: string ``` #### tecs.gfx.animation.GridOptions.imageWidth field Caller-writable. Sets the required image width in pixels. ```teal tecs.gfx.animation.GridOptions.imageWidth: number ``` #### tecs.gfx.animation.GridOptions.imageHeight field Caller-writable. Sets the required image height in pixels. ```teal tecs.gfx.animation.GridOptions.imageHeight: number ``` #### tecs.gfx.animation.GridOptions.frameWidth field Caller-writable. Sets the required frame width in pixels. ```teal tecs.gfx.animation.GridOptions.frameWidth: number ``` #### tecs.gfx.animation.GridOptions.frameHeight field Caller-writable. Sets the required frame height in pixels. ```teal 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. ```teal tecs.gfx.animation.GridOptions.margin: number ``` #### tecs.gfx.animation.GridOptions.spacing field Caller-writable. Sets the gap between neighboring cells and defaults to zero. ```teal 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. ```teal 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. ```teal 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. ```teal 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`. ```teal tecs.gfx.animation.GridOptions.duration: number ``` #### tecs.gfx.animation.GridOptions.tags field Caller-writable. Defines optional named tags over the frames. ```teal tecs.gfx.animation.GridOptions.tags: {string: Tag} ``` #### tecs.gfx.animation.GridOptions.slices field Caller-writable. Defines optional named slices. ```teal 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. ```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) | #### tecs.gfx.animation.Looped.entity field Read-only. Identifies the entity whose animation looped. ```teal tecs.gfx.animation.Looped.entity: integer ``` #### tecs.gfx.animation.Looped.sheet field Read-only. Reports the sheet that looped. ```teal 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. ```teal tecs.gfx.animation.Looped.tag: string ``` #### tecs.gfx.animation.Looped:__call metamethod 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. | ### tecs.gfx.animation.Pivot record 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) | #### 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. ```teal 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. ```teal 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. ```teal 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. ```teal 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. ```teal 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. ```teal tecs.gfx.animation.Pivot.halfY: number ``` ### tecs.gfx.animation.PlayOptions record Configures `of` and `play`. ```teal 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. ```teal 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. ```teal tecs.gfx.animation.PlayOptions.loop: boolean ``` #### tecs.gfx.animation.PlayOptions.playing field Caller-writable. Controls whether playback starts immediately. Defaults to true. ```teal tecs.gfx.animation.PlayOptions.playing: boolean ``` ### tecs.gfx.animation.Rect record 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 ``` #### tecs.gfx.animation.Rect.x field Caller-writable. Sets the frame's left edge in image pixels. ```teal tecs.gfx.animation.Rect.x: number ``` #### tecs.gfx.animation.Rect.y field Caller-writable. Sets the frame's top edge in image pixels. ```teal tecs.gfx.animation.Rect.y: number ``` #### tecs.gfx.animation.Rect.w field Caller-writable. Sets the frame width in pixels. ```teal tecs.gfx.animation.Rect.w: number ``` #### tecs.gfx.animation.Rect.h field Caller-writable. Sets the frame height in pixels. ```teal 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`. ```teal tecs.gfx.animation.Rect.duration: number ``` ### tecs.gfx.animation.RectsOptions record Configures `newRectSheet`. ```teal 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. ```teal tecs.gfx.animation.RectsOptions.name: string ``` #### tecs.gfx.animation.RectsOptions.imageWidth field Caller-writable. Sets the required image width in pixels. ```teal tecs.gfx.animation.RectsOptions.imageWidth: number ``` #### tecs.gfx.animation.RectsOptions.imageHeight field Caller-writable. Sets the required image height in pixels. ```teal tecs.gfx.animation.RectsOptions.imageHeight: number ``` #### tecs.gfx.animation.RectsOptions.frames field Caller-writable. Sets the required frame rects in address order. ```teal tecs.gfx.animation.RectsOptions.frames: {Rect} ``` #### tecs.gfx.animation.RectsOptions.tags field Caller-writable. Defines optional named tags over the frames. ```teal tecs.gfx.animation.RectsOptions.tags: {string: Tag} ``` #### tecs.gfx.animation.RectsOptions.slices field Caller-writable. Defines optional named slices. ```teal tecs.gfx.animation.RectsOptions.slices: {Slice} ``` ### tecs.gfx.animation.Sheet record 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 ``` #### tecs.gfx.animation.Sheet.name field Read-only. Reports the registered name that snapshots store. ```teal tecs.gfx.animation.Sheet.name: string ``` #### tecs.gfx.animation.Sheet.id field 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 ``` #### tecs.gfx.animation.Sheet.count field Read-only. Reports the number of frames and the largest index `rect`, `uv` and `sprite` accept. ```teal 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. ```teal 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. ```teal 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`](/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`. | #### tecs.gfx.animation.Sheet:cycle Instance 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. | #### tecs.gfx.animation.Sheet:duration Instance 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. | #### tecs.gfx.animation.Sheet:frameAt Instance 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. | #### tecs.gfx.animation.Sheet:hasTag Instance 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. | #### 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. ```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. | #### 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. ```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` | | #### tecs.gfx.animation.Sheet:rect Instance 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` | | #### tecs.gfx.animation.Sheet:slice Instance 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. | #### tecs.gfx.animation.Sheet:sliceId Instance 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. | #### 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. ```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) | | #### tecs.gfx.animation.Sheet:sliceName Instance 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. | #### 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. ```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. | #### 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. ```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) | | #### 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. ```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. | #### tecs.gfx.animation.Sheet:tagName Instance 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. | #### 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`](/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` | | ### tecs.gfx.animation.Slice record A named region that moves across the frames. ```teal 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. ```teal tecs.gfx.animation.Slice.name: string ``` #### tecs.gfx.animation.Slice.data field Caller-writable. Stores free text carried by Aseprite. ```teal tecs.gfx.animation.Slice.data: string ``` #### tecs.gfx.animation.Slice.keys field Caller-writable. Sets at least one key in frame order. ```teal tecs.gfx.animation.Slice.keys: {SliceKey} ``` ### tecs.gfx.animation.SliceKey record 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 ``` #### tecs.gfx.animation.SliceKey.frame field Caller-writable. Sets the first frame on which this key takes effect, counting from one. ```teal tecs.gfx.animation.SliceKey.frame: integer ``` #### tecs.gfx.animation.SliceKey.x field Caller-writable. Sets the slice rectangle's left edge in frame pixels. ```teal tecs.gfx.animation.SliceKey.x: number ``` #### tecs.gfx.animation.SliceKey.y field Caller-writable. Sets the slice rectangle's top edge in frame pixels. ```teal tecs.gfx.animation.SliceKey.y: number ``` #### tecs.gfx.animation.SliceKey.w field Caller-writable. Sets the slice rectangle's width in pixels. ```teal tecs.gfx.animation.SliceKey.w: number ``` #### tecs.gfx.animation.SliceKey.h field Caller-writable. Sets the slice rectangle's height in pixels. ```teal 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. ```teal 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. ```teal tecs.gfx.animation.SliceKey.centerY: number ``` #### tecs.gfx.animation.SliceKey.centerW field Caller-writable. Sets the nine-slice center's width in pixels. ```teal tecs.gfx.animation.SliceKey.centerW: number ``` #### tecs.gfx.animation.SliceKey.centerH field Caller-writable. Sets the nine-slice center's height in pixels. ```teal 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. ```teal 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. ```teal tecs.gfx.animation.SliceKey.pivotY: number ``` ### tecs.gfx.animation.Tag record A named span of frames, as the constructors take it. ```teal 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. ```teal tecs.gfx.animation.Tag.from: integer ``` #### tecs.gfx.animation.Tag.to field Caller-writable. Sets the last frame index in the inclusive span. ```teal tecs.gfx.animation.Tag.to: integer ``` #### tecs.gfx.animation.Tag.direction field Caller-writable. Sets the playback direction and defaults to `"forward"`. ```teal 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. ```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. | ### tecs.gfx.animation.byId Static 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. | ### 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. ```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. | ### tecs.gfx.animation.findSheetById Static 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. | ### tecs.gfx.animation.findSheetByName Static 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. | ### 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. ```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. | ### 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. ```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. | ### 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. ```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`. | ### tecs.gfx.animation.of Static 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. | ### 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. ```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. ### 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`](/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. ### 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. ```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`. | ### 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. ```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` | | ### 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. ```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. | ### 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. ```teal 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. ```teal 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. ```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 ### tecs.gfx.animation.DEFAULT_DURATION variable Read-only. Reports how many milliseconds a frame remains visible when nothing overrides its duration. ```teal tecs.gfx.animation.DEFAULT_DURATION: number ```