Skip to main content
Glama

tween_cels

Destructive

Interpolates one Aseprite cel's scale, rotation, and opacity across selected frames, creating animation inbetweens from a single drawing without pixel blending.

Instructions

Scale, turn and fade one drawn cel across frames, in one Aseprite launch.

`offset_cels` moves a cel along a path, which is one of the four things an inbetween
does. This is the other three. The cel on the **first listed frame is the source**,
and every listed frame becomes that one drawing resampled by its share of the change:
frame nine is sampled from the original and not from frame eight, so the rounding
never compounds.

**It interpolates a transform, not pixels.** Blending two different drawings gives a
double exposure, two silhouettes at half strength, which reads as a mistake rather
than as motion. So this takes one drawing, and when two cels genuinely differ in shape
there is no honest automatic inbetween: draw the second pose and tween each one out
from its own extreme, or express the difference as a scale and a turn, which most of
them are.

Args:
    frames: The frames to write, in the order the change passes through them. The
        first is the source, and it is rewritten too when `scale_from`, `rotate_from`
        or `opacity_from` is not the identity.
    scale_from, scale_to: The scale at the first and last frame, on both axes.
    scale_y_from, scale_y_to: Override the vertical scale, for squash and stretch,
        where the two axes go opposite ways (0.7 tall against 1.25 wide is a squash
        that keeps its volume). Unset means the same as the horizontal, which is a
        zoom and not a squash.
    rotate_from, rotate_to: Clockwise degrees at the first and last frame, snapped to
        whole degrees. Quarter turns are exact and lose nothing; sampling within about
        15 degrees of one shuffles the edge pixels rather than turning the shape, and
        the result says so in `warnings` instead of pretending otherwise.
    opacity_from, opacity_to: Cel opacity, 0 to 255. This sets the cel's own opacity
        and never bakes alpha into the pixels: a baked fade invents colours that are
        not on the palette. It is the per-frame `set_cel_opacity` done in one call.
    ease: How the change is *spaced*: `linear`, `ease_in` (starts slow), `ease_out`
        (arrives slow), `ease_in_out`, or `gravity` (accelerating, as a falling object
        does). Easing belongs in one place at a time, and `apply_timing_curve` carries
        the durations.
    anchor: The point the transform holds still, taken from the cel's own drawn
        bounds: `center`, `top`, `bottom`, `left` or `right`. This matters more than it
        looks. A scale about the centre makes a ball grow in every direction; a scale
        about `bottom` makes it squash *onto the ground*, which is the one that reads
        as weight, and `validate_loop`'s contact-edge check then confirms that the
        contact row did not move.

Refuses rather than doing something approximate: fewer than two frames, a frame listed
twice, a from and to that are identical on every channel (each frame would be
rewritten with the drawing the source already holds), a scale of zero or below, a
group or tilemap layer, a source frame with no cel or nothing drawn on it, a frame
whose transform lands entirely off the canvas, and any frame that shares its image
with another frame. That last one is the sharp edge: linked cels share one image, one
position and one opacity, so a tween written into a link group would change every
frame in it. The refusal names the frames and points at `unlink_cels`.

Every listed frame after the first is **overwritten** with the transformed source
rather than blended with what was there. `steps[].bounds` is the written cel's own
content box, so a scale series can be checked instead of trusted: `rendered_monotone`
is that check, and it is omitted while the cel is also rotating, because a turning
shape's bounding box oscillates by design. `steps[].drawn_pixels` is how many opaque
samples that frame took; `pixels_written` is what landed, and the two differ only when
an active selection masked part of it, which `pixels_outside_selection` then reports.

Sampling is nearest-neighbour and copies the source pixel whole, so no colour appears
that the drawing did not already contain and `palette_conformance` is unchanged.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
easeNoDefault: "linear".linear
layerYes
anchorNoDefault: "center".center
framesYes
filenameYes
scale_toNoDefault: 1.0.
rotate_toNoDefault: 0.0.
opacity_toNoDefault: 255.
scale_fromNoDefault: 1.0.
scale_y_toNo
rotate_fromNoDefault: 0.0.
opacity_fromNoDefault: 255.
scale_y_fromNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Addedv0.10.0

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnly=false, and the description substantiates the mutation profile in depth: every listed frame after the first is overwritten, the source frame is rewritten when the from-values are non-identity, and a long list of refusal conditions is given (fewer than two frames, duplicate frames, identical from/to, zero scale, group/tilemap layer, linked cels sharing one image, off-canvas transforms). It even discloses backward-looking behavior like warnings on near-quarter rotations and palette_conformance being unchanged. Far beyond what annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose before the args, and the parentheticals (squash example, contact-edge reference) earn their space. It is long, but the length is largely justified by 13 parameters with non-obvious transform semantics and a large refusal surface; a few clauses could be tightened without loss.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description carries the full return burden and does: steps[].bounds, rendered_monotone (and why it is omitted while rotating), drawn_pixels vs pixels_written, and pixels_outside_selection. Combined with the refusal list and mutation semantics, an agent has everything needed to call and interpret it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 62% schema coverage and 13 parameters, the description compensates heavily: it defines frames ordering and source semantics, the scale_y_from/to override for squash-and-stretch, rotate snapping behavior, opacity as per-cel non-baked alpha, the ease enumeration with meanings, and anchor with the bottom-anchor weight argument. This adds substantial meaning the bare 'Default: 1.0' schema entries do not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb triple (scale, turn, fade) on a specific resource (one drawn cel) across frames, and explicitly positions itself against the sibling offset_cels ('this is the other three' inbetweens). An agent can distinguish this from offset_cels, set_cel_opacity, and apply_timing_curve without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Not only says when to use it but when NOT to: interpolating two genuinely different drawings is refused because it produces a double exposure, and the description routes the agent to draw the second pose or express the delta as scale/turn. It also names the boundary with apply_timing_curve (easing vs durations) and offset_cels explicitly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Deploy Server

Other Tools