Layers
Create, arrange and configure layers. Groups are folders of layers: a layer's parentId names its group (nil at the top level) and app.moveLayer positions count within a group (0 = bottom). Hiding or locking a group hides or locks everything inside it. A group at full opacity with blend mode "normal" is pass-through (its layers blend straight into what's below) unless its isolated flag is set; an isolated group, or any other opacity or mode, composites its layers together first. (25 functions)
app.addAdjustmentLayer(name?, effects?, parentId?) — changes, undoable
Adds an adjustment layer on top of every other layer (or inside the group parentId): it holds no pixels, and its effects change everything composited below it in its group (or the whole picture), on every frame, at the layer's opacity. Clip it to change only the layer below. Makes it active.
name(string, optional) — Defaults to "Adjustment N".effects(table, optional) — Its effects, as for app.setLayerEffects (colour and per-pixel kinds only). Omitted = none yet.parentId(string, optional) — A group to add it to (on top of its layers); omitted = the top level.
Returns (string): The new layer's id.
app.addGroup(name?, parentId?) — changes, undoable
Adds a new empty layer group on top of every other layer (or inside the group parentId) and makes it active. Put layers in it with app.moveLayer or app.groupLayers.
name(string, optional) — Defaults to "Group N".parentId(string, optional) — A group to nest it in (on top of its layers); omitted = the top level.
Returns (string): The new group's id.
app.addLayer(name?, parentId?) — changes, undoable
Adds a new blank layer on top of every other layer (or on top of the group parentId's layers) and makes it active.
name(string, optional) — Defaults to "Layer N".parentId(string, optional) — A group to add it to (on top of its layers); omitted = the top level.
Returns (string): The new layer's id.
app.backgroundFromLayer(layerId?, backgroundColor?) — changes, undoable, refused on a locked layer
Layer > "Background from Layer": converts an image layer into the sprite's Background layer: moved to the bottom, named "Background", and made fully opaque (transparent pixels take the background colour). Throws if the sprite already has a Background layer.
layerId(string, optional) — The image layer to convert; omitted = the bottom-most image layer.backgroundColor(color, optional) — What fills the transparent pixels. Defaults to the current background colour.
Returns (string): The converted layer's id.
app.bakeLayerEffects(layerId) — changes, undoable, refused on a locked layer
Renders an image layer's enabled effects into all of its cels and removes them, as a single undo step. Cels grow to hold shadows and outlines (clipped to the canvas); indexed sprites snap the result to each frame's palette. Throws on a locked layer or one without effects.
layerId(string)
Returns nothing.
app.duplicateLayer(layerId) — changes, undoable
Clones a layer (a group with everything inside it) and every cel painted on it, inserting the copy directly above the original and making it active.
layerId(string)
Returns (string): The copy's layer id.
app.flattenGroup(layerId) — changes, undoable, refused on a locked layer
Replaces a group and everything in it with one image layer (same id, name, opacity, blend mode and place) holding its layers composited together on every frame. Hidden, draft and reference layers inside are deleted, like Flatten.
layerId(string) — The group to flatten.
Returns nothing.
app.flattenSprite(visibleOnly?, backgroundColor?) — changes, undoable
Layer > Flatten: collapses every top-level layer (hidden ones included) into one layer, per frame, exactly as it renders with them shown; with visibleOnly, only the visible ones, keeping the hidden ones. A visible Background layer stays the Background (fully opaque); otherwise the result is a new layer named Flattened. Throws if there's nothing to flatten.
visibleOnly(boolean, optional) — Flatten Visible: flatten only the visible top-level layers and keep the hidden ones. Default false: everything, hidden layers included.backgroundColor(color, optional) — Only when the result is the Background layer (a visible Background is flattened): what fills the pixels nothing covers. Defaults to the current background colour.
Returns nothing.
app.getActiveLayerId() — reads
The currently active layer's id, or nil if none.
Returns (string): Layer id or nil.
app.getLayer(layerId) — reads
One layer, in the same shape as an app.getLayers entry, or nil if there's no such layer.
layerId(string)
Returns (table): Layer table or nil.
app.getLayers() — reads
Every layer, bottom to top (a group sits just above its layers), as { id, name, type ("image" | "tilemap" | "reference" | "group"), parentId (the group it's in; nil at the top level), depth (0 = top level), index (0 = bottom of the whole stack), position (slot among its parent's layers, 0 = bottom; what app.moveLayer takes), opacity (0-1), visible, locked, movementLocked, background (true on the Background layer), clipped (a clipping mask: shows only where the nearest unclipped layer below it has pixels), continuous (app.duplicateFrame links its cels instead of copying them), blendMode, collapsed (groups), tileset = { tileWidth, tileHeight, tileCount, matchFlipH, matchFlipV, matchRotate } (tilemap layers), reference = { width, height } (reference layers) }. visible/locked/movementLocked are the layer's own flags; a hidden, locked or movement-locked group also hides, locks or pins everything inside it.
Returns (table): Array of layer tables.
app.getReferenceTransform(layerId, frameId) — reads
Where a reference layer's image sits on one frame, as { x, y, width, height } in sprite pixels, or nil if it's blank there.
layerId(string) — A reference layer.frameId(string)
Returns (table): Transform table or nil.
app.groupLayers(layerIds, name?) — changes, undoable
Puts layers (groups with everything inside them) into a new group at the topmost one's position, keeping their order, and makes the group active.
layerIds(table) — Array of layer ids, all in the same group (or all at the top level).name(string, optional) — Defaults to "Group N".
Returns (string): The new group's id.
app.layerFromBackground() — changes, undoable
Layer > "Layer from Background": turns the Background layer into an ordinary layer (transparency and movement allowed again). Throws if the sprite has no Background layer.
Returns (string): The converted layer's id.
app.mergeLayerDown(layerId) — changes, undoable, refused on a locked layer
Composites a layer (or a whole group, as it renders) onto the layer directly below it in the same group, then deletes it; a clipping base takes its clipped layers with it. The result looks the same, and the layer below ends up at opacity 100% and the normal blend mode. Throws if there's nothing below it in its group, what's below isn't an image layer, or an unclipped layer would merge onto a clipped one.
layerId(string)
Returns nothing.
app.mergeLayers(layerIds) — changes, undoable, refused on a locked layer
Merges layers (groups with everything inside them) into one image layer exactly as they render together, at the topmost one's position and with its name, and makes it active. With the Background among them the result is the Background.
layerIds(table) — Array of two or more layer ids, all in the same group (or all at the top level). Hidden ones are merged too.
Returns (string): The merged layer's id.
app.mergeLayerUp(layerId) — changes, undoable, refused on a locked layer
Merges an image layer into the layer directly above it in the same group: the result looks exactly like Merge Down of that layer, but takes its name and colour tag. Throws if there's nothing above it in its group or it isn't an image layer.
layerId(string)
Returns nothing.
app.moveLayer(layerId, position, parentId?) — changes, undoable
Moves a layer (a group with everything inside it) to a new position, optionally into another group. Throws when moving a group into itself.
layerId(string)position(number) — Its slot among the parent's other layers afterwards (0 = bottom), clamped to the valid range.parentId(string, optional) — The group to move it into; "" = the top level; omitted = stay in its current group.
Returns nothing.
app.removeLayer(layerId) — changes, undoable
Removes a layer and any cels painted on it; removing a group removes everything inside it. Throws if it would leave no (non-group) layer.
layerId(string)
Returns nothing.
app.setActiveLayer(layerId) — changes
Makes a layer the active one (what clicking it in the layer panel does). Not an undoable edit.
layerId(string)
Returns nothing.
app.setLayerEffects(layerId, effects) — changes, undoable
Sets a layer's non-destructive effects: ops run on the layer's pixels (a group's composited children) every time the sprite is composited, in order, and are never written into the cels (app.bakeLayerEffects does that). Allowed on a locked layer. Not for reference layers; the Background layer takes colour effects only.
layerId(string)effects(table) — The layer's whole effect list, bottom first ({}clears it). Each entry is{ kind = "levels", ...that effect's fields, enabled = true }; read the current list fromapp.getLayers, change it and pass it back (entries keep theirid). Kinds: brightnessContrast, hueSaturation, colorCurve, levels, threshold, gradientMap, colorBalance, invert, replaceColor, posterize take the fields of the matching app.* adjustment; outline takesplace,width,shape,color; shadow takesplace,dx,dy,spread,shape,softness(0-8 px of soft edge),edge("dithered", "hard" or "smooth": how a soft edge is drawn),color; noise (amount,size,mono,seed), dither (pattern,levels,strength), scanlines (period,thickness,offset,strength,mask), vignette (strength,radius,softness,color), paletteSwap (from,to,tolerance), blur (radius,shape,edge,colors), bloom (threshold,radius,intensity,edge,colors), edgeDetect (strength,mode,invert,color), smoother (size), pixelate (size), chromatic (dx,dy), wave (axis,amplitude,wavelength,phase), bend (axis,amount), distortion (axis,band,amount,density,seed), parallax (shift), echo (count,dx,dy,fade), antiAlias (a,anyA,b,steps,into,strength,colors: as app.antiAlias), autoShade (target,base,angle,highlights,shadows,width,hueShift,chroma,rim,outline,colors,ramp: as app.autoShade). Blur and bloom can snap for pixel art:edgeis "smooth", "hard" or "dithered",colorsis "any" or "palette" (the frame's palette, the default on indexed sprites). Animate a number or colour parameter withtracks = { dx = { { frame = frameId, value = 0 }, { frame = otherFrameId, value = 4, easing = ... } } }(the path is the field, orvalue.gamma,shadows.redand so on; a missing easing is linear) andtiming = "frames"or"time". Every colour (color,below,above,from,to, a gradient stop'scolor,a,b,base, a colour key'svalue) is"#rgb","#rrggbb","#rrggbbaa"or{ r, g, b, a }(adefaults to 255); the colour lists (paletteSwap'sfromandto, autoShade'sramp) take those too, alpha ignored. Reads (app.getLayers) return colours as{ r, g, b, a }tables and colour lists as"#rrggbb"strings.
Returns nothing.
app.setLayerProps(layerId, props) — changes, undoable
Updates one or more properties of a layer or group.
layerId(string)props(table) — Omitted keys are left unchanged.name(string) — The layer's name.opacity(number 0–1) — Layer opacity. A group below 1 composites its layers together first (it is isolated).visible(boolean) — Whether the layer is shown (and, for scripts, exported). A hidden group hides everything inside it.locked(boolean) — A locked layer's content can't be changed by anything, scripts included. Locking a group locks everything inside it.movementLocked(boolean) — A movement-locked layer's cels can't be moved (movePixels, moveCels, a transformPixels shift, reference placement) — painting still works. Locking a group's movement locks everything inside it.clipped(boolean) — Clipping mask: the layer only shows where the nearest unclipped layer below it in the same group (its base) has pixels, and the base's blend mode applies to the whole stack. Not for reference layers or the Background layer.draft(boolean) — Draft layer: shown while you work but never exported, flattened or stamped (a draft group takes everything inside it along). Not for reference layers or the Background layer.continuous(boolean) — Continuous layer (Aseprite's): New Frame (app.duplicateFrame withoutlinked) links this layer's cel to the original's instead of copying it. Not for groups.isolated(boolean) — Groups only: composite the group's layers on their own first, then blend the result as one image (Photoshop's Normal group). Off, a group at normal blend and opacity 1 is pass-through: its layers blend straight into what's below. Any other blend mode or opacity isolates the group anyway.blendMode(BlendMode: "normal" | "multiply" | "screen" | "overlay" | "darken" | "lighten" | "color-dodge" | "color-burn" | "hard-light" | "soft-light" | "difference" | "exclusion" | "hue" | "saturation" | "color" | "luminosity" | "addition" | "subtract" | "divide") — How the layer blends with those below. A group with a mode other than "normal" composites its layers together first (it is isolated).
Returns nothing.
app.setReferenceTransform(layerId, frameId, x, y, width, height) — changes, undoable, refused on a locked layer
Repositions/resizes a reference layer's placement on one frame (sprite-space). A width or height <= 0 clears it (blank on that frame) instead. Throws if layerId isn't a reference layer.
layerId(string)frameId(string)x(number)y(number)width(number)height(number)
Returns nothing.
app.stampVisible(name?) — changes, undoable
Adds a new layer holding everything visible, per frame, exactly as Flatten would make it (reference and draft layers left out) but keeping every layer, above the active layer's top-level block, and makes it active.
name(string, optional) — Defaults to "Visible".
Returns (string): The new layer's id.
app.ungroupLayer(layerId) — changes, undoable
Removes a group, moving its layers up into its place. Their own properties are kept; the group's opacity, blend mode and visibility are dropped, not baked in.
layerId(string) — A group.
Returns nothing.
As Markdown: layers.md.