# pxstud.io Lua scripting API — Frames & tags

> Part of the pxstud.io Lua scripting reference, whose overview (https://pxstud.io/docs/scripting.md) explains its conventions. The option groups and types it refers to are in https://pxstud.io/docs/scripting/option-groups.md and https://pxstud.io/docs/scripting/types.md. Everything in one file: https://pxstud.io/llms-full.txt. The whole site's index: https://pxstud.io/llms.txt.

### Frames & tags
The timeline: frames, their durations, and animation tags.

#### `app.addFrame(frameId?, durationMs?, before?)` — changes, undoable
Adds a new blank frame ("New Empty Frame" in the Frame menu), after `frameId` or before it with `before`. The new frame becomes the active one.

- `frameId` (string, optional) — The frame to insert next to. Omit (or pass nil) to append at the end.
- `durationMs` (number, optional) — Defaults to the sprite's standard frame duration.
- `before` (boolean, optional) — True inserts the new frame before `frameId` instead of after it, which is the only way to add a frame ahead of the first one. Needs a `frameId`.

Returns (string): The new frame's id.

#### `app.addTag(fromFrameId, toFrameId, name?, color?, direction?)` — changes, undoable
Creates a new tag spanning [fromFrameId, toFrameId].

- `fromFrameId` (string)
- `toFrameId` (string)
- `name` (string, optional) — Defaults to "Tag N".
- `color` (string, optional) — Hex color.
- `direction` (TagDirection: "forward" | "reverse" | "pingpong" | "pingpongReverse", optional) — Playback direction; defaults to forward.

Returns (string): The new tag's id.

#### `app.bakeTween(layerId, frameId)` — changes, undoable, refused on a locked layer
Removes the tween that starts at frameId but keeps every in-between as a plain cel, so they no longer redraw. One undo step.

- `layerId` (string) — An image layer (not the Background).
- `frameId` (string) — The start keyframe's frame: the layer's own cel there (not a link) is what gets tweened.

Returns nothing.

#### `app.duplicateFrame(frameId, linked?)` — changes, undoable
Duplicates a frame (and its cels) immediately after it, making the copy active ("New Frame" in the Frame menu).

- `frameId` (string)
- `linked` (boolean, optional) — True links every copied cel to the original's (shared images), false copies every one; omitted, continuous layers link and the others copy.

Returns (string): The copy's frame id.

#### `app.getActiveFrameId()` — reads
The currently active frame's id, or nil if none.

Returns (string): Frame id or nil.

#### `app.getFrame(frameId)` — reads
One frame as { id, index, durationMs }, or nil if there's no such frame.

- `frameId` (string)

Returns (table): Frame table or nil.

#### `app.getFrames()` — reads
Every frame in timeline order as { id, index (0 = first), durationMs }.

Returns (table): Array of frame tables.

#### `app.getTags()` — reads
Every animation tag as { id, name, fromFrameId, toFrameId, fromIndex, toIndex (inclusive frame indices), color (hex), direction ("forward" | "reverse" | "pingpong" | "pingpongReverse"), repeat (times played before continuing; absent = loops forever) }.

Returns (table): Array of tag tables.

#### `app.moveFrame(frameId, toIndex)` — changes, undoable
Moves a frame to a new position in the timeline.

- `frameId` (string)
- `toIndex` (number) — Destination position in the final ordering, clamped to the valid range.

Returns nothing.

#### `app.regenerateTween(layerId, frameId, revertFrameIds?)` — changes, undoable, refused on a locked layer
Redraws the in-betweens of the tween that starts at frameId from its start cel. Frames you edited by hand are skipped unless listed in revertFrameIds. A tween whose end frame is gone can't be redrawn. One undo step; nothing to change adds none.

- `layerId` (string) — An image layer (not the Background).
- `frameId` (string) — The start keyframe's frame: the layer's own cel there (not a link) is what gets tweened.
- `revertFrameIds` (table, optional) — A list of in-between frame ids whose hand-edited cels are redrawn too.

Returns nothing.

#### `app.removeFrame(frameId)` — changes, undoable
Removes a frame and any cels, tile placements and reference placements on it. Throws if it is the last remaining frame.

- `frameId` (string)

Returns nothing.

#### `app.removeTag(tagId)` — changes, undoable
Removes a tag (the frames it spanned are untouched).

- `tagId` (string)

Returns nothing.

#### `app.removeTween(layerId, frameId)` — changes, undoable, refused on a locked layer
Removes the tween that starts at frameId, deleting its generated in-betweens (frames you edited by hand stay as plain cels). One undo step.

- `layerId` (string) — An image layer (not the Background).
- `frameId` (string) — The start keyframe's frame: the layer's own cel there (not a link) is what gets tweened.

Returns nothing.

#### `app.reverseFrames(fromFrameId?, toFrameId?)` — changes, undoable
Reverses the order of the frames in a range (all frames when omitted) as one undo step. Cels, links, tilemap placements and reference transforms move with their frames; tags keep covering the same positions.

- `fromFrameId` (string, optional) — First frame of the range; omit (with toFrameId) to reverse every frame.
- `toFrameId` (string, optional) — Last frame of the range (inclusive).

Returns nothing.

#### `app.setActiveFrame(frameId)` — changes
Makes a frame the active one (what clicking it in the timeline does). Not an undoable edit.

- `frameId` (string)

Returns nothing.

#### `app.setAllFrameDurations(durationMs)` — changes, undoable
Sets every frame in the sprite to the same playback duration.

- `durationMs` (number)

Returns nothing.

#### `app.setFrameDuration(frameId, durationMs)` — changes, undoable
Sets one frame's playback duration.

- `frameId` (string)
- `durationMs` (number) — Whole milliseconds, 1-65535.

Returns nothing.

#### `app.setFrameProps(frameId, props)` — changes, undoable
Sets a frame's colour label and/or lock.

- `frameId` (string)
- `props` (table) — Omitted keys are left unchanged.
  - `color` (string) — The frame's timeline label as "#rrggbb"; an empty string clears it.
  - `locked` (boolean) — A locked frame's cels can't be edited by anything, scripts included, and the frame can't be removed, moved or re-timed.

Returns nothing.

#### `app.setTagProps(tagId, props)` — changes, undoable
Updates one or more properties of a tag.

- `tagId` (string)
- `props` (table) — Omitted keys are left unchanged.
  - `name` (string) — The tag's name.
  - `color` (string) — The tag's color as "#rrggbb".
  - `direction` (TagDirection: "forward" | "reverse" | "pingpong" | "pingpongReverse") — Playback direction.
  - `fromFrameId` (string) — The first frame of the span.
  - `toFrameId` (string) — The last frame of the span.
  - `repeat` (integer ≥ 0) — How many times playback plays the tag before continuing (Aseprite's tag Repeat); 0 loops forever.

Returns nothing.

#### `app.setTween(layerId, frameId, opts?)` — changes, undoable, refused on a locked layer
Tweens a layer's cel at frameId to a later frame: the frames in between get real cels (the start cel's picture moved, scaled, rotated, skewed and faded by the options, eased as chosen) that stay linked to the recipe, so they redraw when the start cel changes. Replaces a tween already starting there. One undo step. Frames you have drawn on stay as they are. Returns the tween's id.

- `layerId` (string) — An image layer (not the Background).
- `frameId` (string) — The start keyframe's frame: the layer's own cel there (not a link) is what gets tweened.
- `opts` (table, optional)
  - `to` (string) — Required. The id of the end keyframe's frame: a later frame on the same layer. The in-betweens are the frames strictly between; the end frame keeps your own drawing.
  - `from` ({ dx, dy, scaleX, scaleY, rotation, skewX, skewY, opacity }, each optional (missing = no change: 0, 1, 0, 0, 1); default no change) — The pose at the start keyframe (usually left alone).
  - `end` ({ dx, dy, scaleX, scaleY, rotation, skewX, skewY, opacity }, each optional (missing = no change: 0, 1, 0, 0, 1); default no change) — The pose reached at the end keyframe: translation in sprite pixels, scale (1 = same), rotation and skew in degrees, opacity multiplier 0..1.
  - `ease` (TweenEaseFamily: "linear" | "hold" | "sine" | "quad" | "cubic" | "quart" | "quint" | "expo" | "circ" | "back" | "elastic" | "bounce"; default "quad") — The easing curve for every track. Ignored when `steps` is given.
  - `mode` (TweenEaseMode: "in" | "out" | "inOut"; default "inOut") — Which end of the tween `ease` shapes (ignored by linear and hold).
  - `overshoot` (number 0–10) — back easing: how far it winds up or overshoots (default 1.70158). Only with ease = "back".
  - `amplitude` (number 1–10) — elastic easing: peak size (default 1). Only with ease = "elastic".
  - `period` (number 0.01–1) — elastic easing: wobble length as a fraction of the span (default 0.3). Only with ease = "elastic".
  - `bounces` (integer 1–8) — bounce easing: number of landings (default 4). Only with ease = "bounce".
  - `steps` (integer 1–64) — Quantize progress into this many equal jumps (a stepped, held look) instead of a smooth curve.
  - `curve` (a list of 2-32 anchors { x, y, inX?, inY?, outX?, outY?, corner? }; the first is x = 0, y = 0 and the last x = 1, y = 1, and x rises along the list) — A drawn easing curve through those anchors (cubic beziers; inX/inY and outX/outY are the handles as offsets from the anchor, 0 by default). Replaces `ease` and `steps`.
  - `trackEasing` ({ position?, scale?, rotation?, skew?, opacity?, color? }, each an easing table with the same keys as the easing options (ease, mode, overshoot, amplitude, period, bounces, steps, curve)) — Easing for single tracks, overriding the default one for just those tracks.
  - `color` ({ hue?, saturation?, lightness?, tint? }: hue in degrees (-360..360), saturation and lightness -100..100, tint 0..1) — Colour adjustments reached at the end pose, applied to the start picture (HSL Hue/Saturation, then the tint). Omitted fields stay neutral (0). The `color` track's easing shapes it.
  - `colorFrom` (the same fields as color; default all neutral) — The colour adjustments at the start keyframe (usually left alone).
  - `tintColor` (color ("#rgb", "#rrggbb[aa]" or { r, g, b, a }); default "#ffffff") — The colour the tint mixes toward (its alpha is ignored).
  - `ramp` ({ first, last, shift, wrap? }: palette indices first..last (0-255), shift in whole places (-255..255), wrap true by default) — Indexed sprites only: pixels whose palette index is in first..last (the transparent index excluded) move along that run of the palette by `shift` places over the span, cycling past the ends with wrap and stopping at them otherwise. Ignored on other colour modes. The `color` track's easing shapes it.
  - `path` (TweenPath: "straight" | "arc" | "wave" | "zigzag" | "shake" | "custom"; default "straight") — The route position takes between the poses, as an offset across the straight line.
  - `points` (a list of 2-64 anchors { x, y, inX?, inY?, outX?, outY?, corner? } in sprite pixels relative to the start cel's position; inX/inY and outX/outY are the handles as offsets from the anchor (0 by default)) — custom path: the drawn route, a cubic Bézier through the anchors, travelled at constant speed. Required with path = "custom". The first anchor is the `from` position and the last the `end` position: when `from` or `end` leave out dx/dy they are taken from it, and given ones must match.
  - `orient` (boolean; default false) — Turn the picture to follow the direction of travel along the path (added to the rotation; no turn at the start). Uses `resample` (RotSprite is a good choice).
  - `height` (number) — arc path: the hump height in pixels. Default 8.
  - `pathAmplitude` (number) — wave, zigzag and shake paths: the offset in pixels. Default 4.
  - `cycles` (number 0–64) — wave and zigzag paths: how many full waves long. Default 1.
  - `phase` (number -1–1) — wave path: where in the wave it starts, in turns. Default 0.
  - `seed` (integer ≥ 0) — shake path: the random seed; one seed always jitters the same way. Default 1.
  - `fade` (TweenFade: "alpha" | "dither"; default "alpha") — How the opacity track shows: partial opacity, or a dither dissolve of whole pixels.
  - `ditherPattern` (TweenDither: "bayer2" | "bayer4" | "bayer8" | "cluster"; default "bayer4") — The pattern a dither fade dissolves through, fixed to the canvas so it doesn't crawl as the picture moves. Giving it implies fade = "dither".
  - `crossfade` (boolean; default false) — Fade from the start picture into the end keyframe's own drawing (by the opacity track's easing), dithered or blended per `fade`. The end keyframe's drawing is then an input: editing it redraws the tween.
  - `delay` (integer 0–4096; default 0) — Frames to hold the start pose before moving; the motion then fills the rest of the span.
  - `trackDelay` ({ position?, scale?, rotation?, skew?, opacity?, color? }, each a whole number of frames (0-4096)) — Delays for single tracks, overriding `delay` for just those tracks.
  - `preset` (a preset recipe, as app.tweenPreset returns: { from, end, easing, path, squash, pivotX, pivotY, exposure, shortestRotation, pingPong, trackEasing?, color?, orient?, fade?, delay?, trackDelay? } with distances relative to the start cel's size) — Builds the tween from a preset, scaled to the start cel (distances are fractions of its size, delays fractions of the span). Only `to`, `resample`, `subpixel`, `timing`, `autoRegenerate`, `fade`, `ditherPattern`, `crossfade`, `delay` and `orient` may be given beside it; they override the preset's.
  - `squash` (number 0–1; default 0) — Velocity-based squash and stretch, volume preserving.
  - `pivotX` (number; default 0.5) — Fixed point of scale, rotation and skew, as a fraction of the start cel's width (0.5 = centre).
  - `pivotY` (number; default 0.5) — The same, as a fraction of the start cel's height.
  - `pivotSpace` (TweenPivotSpace: "cel" | "sprite"; default "cel") — What pivotX and pivotY are in. "sprite" makes them a point in sprite pixels, the same for every layer tweened with it.
  - `resample` (TransformInterpolation: "nearest" | "rotsprite" | "bilinear"; default "nearest") — How the pixels are resampled when scale, rotation or skew change. Pure translation always copies pixels exactly.
  - `subpixel` (TweenSubpixel: "round" | "floor" | "monotonic"; default "round") — How fractional positions land on whole pixels.
  - `timing` (TweenTiming: "frames" | "time"; default "frames") — What progress counts.
  - `exposure` (integer 1–8; default 1) — Draw every Nth pose and hold it ("on twos" = 2).
  - `shortestRotation` (boolean; default true) — Rotate the short way round (the change wrapped into -180..180) rather than the exact number of degrees.
  - `pingPong` (boolean; default false) — Out and back: the motion reaches the end pose halfway through the span and returns to the start pose at the end keyframe, so a loop that ends where it began needs no second drawing. The easing shapes each half.
  - `autoRegenerate` (boolean; default true) — Redraw the in-betweens by themselves when the start keyframe or the frames change.

Returns (string): The tween's id.

#### `app.setTweenChain(layerId, frameIds, opts?)` — changes, undoable, refused on a locked layer
Tweens through several keyframes of one layer in one step: one tween from each keyframe to the next, all with the same options (the same as app.setTween without `to`). Tweens already starting at those frames are replaced; others on the layer must not overlap. One undo step. Returns the tweens' ids, in order.

- `layerId` (string) — An image layer (not the Background).
- `frameIds` (table) — The chain's keyframes as a list of frame ids, earliest first (2 or more). A tween runs from each to the next, so neighbours share a keyframe; each but the last needs its own cel.
- `opts` (table, optional)
  - `from` ({ dx, dy, scaleX, scaleY, rotation, skewX, skewY, opacity }, each optional (missing = no change: 0, 1, 0, 0, 1); default no change) — The pose at the start keyframe (usually left alone).
  - `end` ({ dx, dy, scaleX, scaleY, rotation, skewX, skewY, opacity }, each optional (missing = no change: 0, 1, 0, 0, 1); default no change) — The pose reached at the end keyframe: translation in sprite pixels, scale (1 = same), rotation and skew in degrees, opacity multiplier 0..1.
  - `ease` (TweenEaseFamily: "linear" | "hold" | "sine" | "quad" | "cubic" | "quart" | "quint" | "expo" | "circ" | "back" | "elastic" | "bounce"; default "quad") — The easing curve for every track. Ignored when `steps` is given.
  - `mode` (TweenEaseMode: "in" | "out" | "inOut"; default "inOut") — Which end of the tween `ease` shapes (ignored by linear and hold).
  - `overshoot` (number 0–10) — back easing: how far it winds up or overshoots (default 1.70158). Only with ease = "back".
  - `amplitude` (number 1–10) — elastic easing: peak size (default 1). Only with ease = "elastic".
  - `period` (number 0.01–1) — elastic easing: wobble length as a fraction of the span (default 0.3). Only with ease = "elastic".
  - `bounces` (integer 1–8) — bounce easing: number of landings (default 4). Only with ease = "bounce".
  - `steps` (integer 1–64) — Quantize progress into this many equal jumps (a stepped, held look) instead of a smooth curve.
  - `curve` (a list of 2-32 anchors { x, y, inX?, inY?, outX?, outY?, corner? }; the first is x = 0, y = 0 and the last x = 1, y = 1, and x rises along the list) — A drawn easing curve through those anchors (cubic beziers; inX/inY and outX/outY are the handles as offsets from the anchor, 0 by default). Replaces `ease` and `steps`.
  - `trackEasing` ({ position?, scale?, rotation?, skew?, opacity?, color? }, each an easing table with the same keys as the easing options (ease, mode, overshoot, amplitude, period, bounces, steps, curve)) — Easing for single tracks, overriding the default one for just those tracks.
  - `ends` (a list of end pose tables, one per segment (same fields as end)) — Only for app.setTweenChain: a different end pose for each segment, in order; each replaces `end` for its segment.
  - `color` ({ hue?, saturation?, lightness?, tint? }: hue in degrees (-360..360), saturation and lightness -100..100, tint 0..1) — Colour adjustments reached at the end pose, applied to the start picture (HSL Hue/Saturation, then the tint). Omitted fields stay neutral (0). The `color` track's easing shapes it.
  - `colorFrom` (the same fields as color; default all neutral) — The colour adjustments at the start keyframe (usually left alone).
  - `tintColor` (color ("#rgb", "#rrggbb[aa]" or { r, g, b, a }); default "#ffffff") — The colour the tint mixes toward (its alpha is ignored).
  - `ramp` ({ first, last, shift, wrap? }: palette indices first..last (0-255), shift in whole places (-255..255), wrap true by default) — Indexed sprites only: pixels whose palette index is in first..last (the transparent index excluded) move along that run of the palette by `shift` places over the span, cycling past the ends with wrap and stopping at them otherwise. Ignored on other colour modes. The `color` track's easing shapes it.
  - `path` (TweenPath: "straight" | "arc" | "wave" | "zigzag" | "shake" | "custom"; default "straight") — The route position takes between the poses, as an offset across the straight line.
  - `points` (a list of 2-64 anchors { x, y, inX?, inY?, outX?, outY?, corner? } in sprite pixels relative to the start cel's position; inX/inY and outX/outY are the handles as offsets from the anchor (0 by default)) — custom path: the drawn route, a cubic Bézier through the anchors, travelled at constant speed. Required with path = "custom". The first anchor is the `from` position and the last the `end` position: when `from` or `end` leave out dx/dy they are taken from it, and given ones must match.
  - `orient` (boolean; default false) — Turn the picture to follow the direction of travel along the path (added to the rotation; no turn at the start). Uses `resample` (RotSprite is a good choice).
  - `height` (number) — arc path: the hump height in pixels. Default 8.
  - `pathAmplitude` (number) — wave, zigzag and shake paths: the offset in pixels. Default 4.
  - `cycles` (number 0–64) — wave and zigzag paths: how many full waves long. Default 1.
  - `phase` (number -1–1) — wave path: where in the wave it starts, in turns. Default 0.
  - `seed` (integer ≥ 0) — shake path: the random seed; one seed always jitters the same way. Default 1.
  - `fade` (TweenFade: "alpha" | "dither"; default "alpha") — How the opacity track shows: partial opacity, or a dither dissolve of whole pixels.
  - `ditherPattern` (TweenDither: "bayer2" | "bayer4" | "bayer8" | "cluster"; default "bayer4") — The pattern a dither fade dissolves through, fixed to the canvas so it doesn't crawl as the picture moves. Giving it implies fade = "dither".
  - `crossfade` (boolean; default false) — Fade from the start picture into the end keyframe's own drawing (by the opacity track's easing), dithered or blended per `fade`. The end keyframe's drawing is then an input: editing it redraws the tween.
  - `delay` (integer 0–4096; default 0) — Frames to hold the start pose before moving; the motion then fills the rest of the span.
  - `trackDelay` ({ position?, scale?, rotation?, skew?, opacity?, color? }, each a whole number of frames (0-4096)) — Delays for single tracks, overriding `delay` for just those tracks.
  - `squash` (number 0–1; default 0) — Velocity-based squash and stretch, volume preserving.
  - `pivotX` (number; default 0.5) — Fixed point of scale, rotation and skew, as a fraction of the start cel's width (0.5 = centre).
  - `pivotY` (number; default 0.5) — The same, as a fraction of the start cel's height.
  - `pivotSpace` (TweenPivotSpace: "cel" | "sprite"; default "cel") — What pivotX and pivotY are in. "sprite" makes them a point in sprite pixels, the same for every layer tweened with it.
  - `resample` (TransformInterpolation: "nearest" | "rotsprite" | "bilinear"; default "nearest") — How the pixels are resampled when scale, rotation or skew change. Pure translation always copies pixels exactly.
  - `subpixel` (TweenSubpixel: "round" | "floor" | "monotonic"; default "round") — How fractional positions land on whole pixels.
  - `timing` (TweenTiming: "frames" | "time"; default "frames") — What progress counts.
  - `exposure` (integer 1–8; default 1) — Draw every Nth pose and hold it ("on twos" = 2).
  - `shortestRotation` (boolean; default true) — Rotate the short way round (the change wrapped into -180..180) rather than the exact number of degrees.
  - `pingPong` (boolean; default false) — Out and back: the motion reaches the end pose halfway through the span and returns to the start pose at the end keyframe, so a loop that ends where it began needs no second drawing. The easing shapes each half.
  - `autoRegenerate` (boolean; default true) — Redraw the in-betweens by themselves when the start keyframe or the frames change.

Returns (table): The tweens' ids, one per segment, in order.

#### `app.setTweenEnd(layerId, frameId, toFrameId)` — changes, undoable, refused on a locked layer
Moves the end of the tween that starts at frameId to another frame and redraws it. In-betweens that fall outside the new range are deleted (or kept as plain cels if you edited them); the end frame itself is never touched. Fails if the new range would overlap another tween on the layer. One undo step.

- `layerId` (string) — An image layer (not the Background).
- `frameId` (string) — The start keyframe's frame: the layer's own cel there (not a link) is what gets tweened.
- `toFrameId` (string) — The new end keyframe: a later frame on the same layer.

Returns nothing.

#### `app.setTweenStagger(layerIds, frameId, opts?)` — changes, undoable, refused on a locked layer
Tweens several layers with one recipe (the same options as app.setTween, or a preset scaled to each layer's start cel), each layer starting `step` frames after the previous one. With groupPivot the layers scale and rotate about one shared point, so they move as one rigid group. Tweens already starting there are replaced. One undo step. Returns the tweens' ids, in the order of layerIds.

- `layerIds` (table) — The layers to tween, as a list of ids: image layers (not the Background), each with its own cel on frameId. With order = "given" the list order is the stagger order.
- `frameId` (string) — The start keyframe's frame, shared by every layer.
- `opts` (table, optional)
  - `to` (string) — Required. The id of the end keyframe's frame: a later frame on the same layer. The in-betweens are the frames strictly between; the end frame keeps your own drawing.
  - `from` ({ dx, dy, scaleX, scaleY, rotation, skewX, skewY, opacity }, each optional (missing = no change: 0, 1, 0, 0, 1); default no change) — The pose at the start keyframe (usually left alone).
  - `end` ({ dx, dy, scaleX, scaleY, rotation, skewX, skewY, opacity }, each optional (missing = no change: 0, 1, 0, 0, 1); default no change) — The pose reached at the end keyframe: translation in sprite pixels, scale (1 = same), rotation and skew in degrees, opacity multiplier 0..1.
  - `ease` (TweenEaseFamily: "linear" | "hold" | "sine" | "quad" | "cubic" | "quart" | "quint" | "expo" | "circ" | "back" | "elastic" | "bounce"; default "quad") — The easing curve for every track. Ignored when `steps` is given.
  - `mode` (TweenEaseMode: "in" | "out" | "inOut"; default "inOut") — Which end of the tween `ease` shapes (ignored by linear and hold).
  - `overshoot` (number 0–10) — back easing: how far it winds up or overshoots (default 1.70158). Only with ease = "back".
  - `amplitude` (number 1–10) — elastic easing: peak size (default 1). Only with ease = "elastic".
  - `period` (number 0.01–1) — elastic easing: wobble length as a fraction of the span (default 0.3). Only with ease = "elastic".
  - `bounces` (integer 1–8) — bounce easing: number of landings (default 4). Only with ease = "bounce".
  - `steps` (integer 1–64) — Quantize progress into this many equal jumps (a stepped, held look) instead of a smooth curve.
  - `curve` (a list of 2-32 anchors { x, y, inX?, inY?, outX?, outY?, corner? }; the first is x = 0, y = 0 and the last x = 1, y = 1, and x rises along the list) — A drawn easing curve through those anchors (cubic beziers; inX/inY and outX/outY are the handles as offsets from the anchor, 0 by default). Replaces `ease` and `steps`.
  - `trackEasing` ({ position?, scale?, rotation?, skew?, opacity?, color? }, each an easing table with the same keys as the easing options (ease, mode, overshoot, amplitude, period, bounces, steps, curve)) — Easing for single tracks, overriding the default one for just those tracks.
  - `color` ({ hue?, saturation?, lightness?, tint? }: hue in degrees (-360..360), saturation and lightness -100..100, tint 0..1) — Colour adjustments reached at the end pose, applied to the start picture (HSL Hue/Saturation, then the tint). Omitted fields stay neutral (0). The `color` track's easing shapes it.
  - `colorFrom` (the same fields as color; default all neutral) — The colour adjustments at the start keyframe (usually left alone).
  - `tintColor` (color ("#rgb", "#rrggbb[aa]" or { r, g, b, a }); default "#ffffff") — The colour the tint mixes toward (its alpha is ignored).
  - `ramp` ({ first, last, shift, wrap? }: palette indices first..last (0-255), shift in whole places (-255..255), wrap true by default) — Indexed sprites only: pixels whose palette index is in first..last (the transparent index excluded) move along that run of the palette by `shift` places over the span, cycling past the ends with wrap and stopping at them otherwise. Ignored on other colour modes. The `color` track's easing shapes it.
  - `path` (TweenPath: "straight" | "arc" | "wave" | "zigzag" | "shake" | "custom"; default "straight") — The route position takes between the poses, as an offset across the straight line.
  - `points` (a list of 2-64 anchors { x, y, inX?, inY?, outX?, outY?, corner? } in sprite pixels relative to the start cel's position; inX/inY and outX/outY are the handles as offsets from the anchor (0 by default)) — custom path: the drawn route, a cubic Bézier through the anchors, travelled at constant speed. Required with path = "custom". The first anchor is the `from` position and the last the `end` position: when `from` or `end` leave out dx/dy they are taken from it, and given ones must match.
  - `orient` (boolean; default false) — Turn the picture to follow the direction of travel along the path (added to the rotation; no turn at the start). Uses `resample` (RotSprite is a good choice).
  - `height` (number) — arc path: the hump height in pixels. Default 8.
  - `pathAmplitude` (number) — wave, zigzag and shake paths: the offset in pixels. Default 4.
  - `cycles` (number 0–64) — wave and zigzag paths: how many full waves long. Default 1.
  - `phase` (number -1–1) — wave path: where in the wave it starts, in turns. Default 0.
  - `seed` (integer ≥ 0) — shake path: the random seed; one seed always jitters the same way. Default 1.
  - `fade` (TweenFade: "alpha" | "dither"; default "alpha") — How the opacity track shows: partial opacity, or a dither dissolve of whole pixels.
  - `ditherPattern` (TweenDither: "bayer2" | "bayer4" | "bayer8" | "cluster"; default "bayer4") — The pattern a dither fade dissolves through, fixed to the canvas so it doesn't crawl as the picture moves. Giving it implies fade = "dither".
  - `crossfade` (boolean; default false) — Fade from the start picture into the end keyframe's own drawing (by the opacity track's easing), dithered or blended per `fade`. The end keyframe's drawing is then an input: editing it redraws the tween.
  - `delay` (integer 0–4096; default 0) — Frames to hold the start pose before moving; the motion then fills the rest of the span.
  - `trackDelay` ({ position?, scale?, rotation?, skew?, opacity?, color? }, each a whole number of frames (0-4096)) — Delays for single tracks, overriding `delay` for just those tracks.
  - `preset` (a preset recipe, as app.tweenPreset returns: { from, end, easing, path, squash, pivotX, pivotY, exposure, shortestRotation, pingPong, trackEasing?, color?, orient?, fade?, delay?, trackDelay? } with distances relative to the start cel's size) — Builds the tween from a preset, scaled to the start cel (distances are fractions of its size, delays fractions of the span). Only `to`, `resample`, `subpixel`, `timing`, `autoRegenerate`, `fade`, `ditherPattern`, `crossfade`, `delay` and `orient` may be given beside it; they override the preset's.
  - `squash` (number 0–1; default 0) — Velocity-based squash and stretch, volume preserving.
  - `pivotX` (number; default 0.5) — Fixed point of scale, rotation and skew, as a fraction of the start cel's width (0.5 = centre).
  - `pivotY` (number; default 0.5) — The same, as a fraction of the start cel's height.
  - `pivotSpace` (TweenPivotSpace: "cel" | "sprite"; default "cel") — What pivotX and pivotY are in. "sprite" makes them a point in sprite pixels, the same for every layer tweened with it.
  - `resample` (TransformInterpolation: "nearest" | "rotsprite" | "bilinear"; default "nearest") — How the pixels are resampled when scale, rotation or skew change. Pure translation always copies pixels exactly.
  - `subpixel` (TweenSubpixel: "round" | "floor" | "monotonic"; default "round") — How fractional positions land on whole pixels.
  - `timing` (TweenTiming: "frames" | "time"; default "frames") — What progress counts.
  - `exposure` (integer 1–8; default 1) — Draw every Nth pose and hold it ("on twos" = 2).
  - `shortestRotation` (boolean; default true) — Rotate the short way round (the change wrapped into -180..180) rather than the exact number of degrees.
  - `pingPong` (boolean; default false) — Out and back: the motion reaches the end pose halfway through the span and returns to the start pose at the end keyframe, so a loop that ends where it began needs no second drawing. The easing shapes each half.
  - `autoRegenerate` (boolean; default true) — Redraw the in-betweens by themselves when the start keyframe or the frames change.
  - `step` (integer 0–4096; default 0) — Frames between one layer's start and the next's (0 = all together).
  - `order` (TweenStaggerOrder: "topDown" | "bottomUp" | "given"; default "topDown") — Which layer starts first.
  - `length` (TweenStaggerLength: "keep" | "extend"; default "keep") — Whether later layers finish together with the first (keep) or keep the same motion length and end later (extend; the frames must exist).
  - `groupPivot` (boolean; default false) — Scale, rotate and skew every layer about one point: pivotX/pivotY taken as fractions of the box around all the start cels, so the layers move rigidly as a group.

Returns (table): The tweens' ids, one per layer, in the order of layerIds.

#### `app.tweenPreset(id)` — pure
One built-in tween preset by id, or nil. Pass its recipe as app.setTween's preset option: app.setTween(layerId, frameId, { to = endFrameId, preset = app.tweenPreset("popIn").recipe }).

- `id` (string) — A built-in preset's id, e.g. "popIn" or "slideInLeft".

Returns (table): The preset, { id, name, description, frames, recipe }: recipe is the relative tween recipe app.setTween's preset option takes; nil for an unknown id.

#### `app.tweenPresets()` — pure
The built-in tween presets (fade in and out, dither in and out, pop, drop, slides, swoop, shake, hop, squash and stretch, float, swing, spin, blink...), in the order the Tween inspector lists them. Your own presets live in the editor on your device and aren't listed.

Returns (table): A list of presets, each { id, name, description, frames, recipe }: recipe is the relative tween recipe app.setTween's preset option takes.
