# pxstud.io Lua scripting API — Editing context

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

### Editing context
The current colors, brush, symmetry and tool options — shared with the editor's toolbar. Draw commands use them for colors, brush and tool options they aren't given; symmetry is information only and is applied only when you pass it.

#### `app.getContext()` — reads
The editing context — the settings draw commands use for colors, brush and tool options you don't pass, shared with the GUI's toolbar. symmetry is the toolbar's symmetry toggle, readable here but NOT applied to commands implicitly — pass symmetry = app.getContext().symmetry to a draw command to follow it. Fields: { foregroundColor, backgroundColor, brushSize, brushShape, brushAngle, customBrush, pixelPerfect, eraserRightClick, ink, shades, stabilizer, pressureSize, pressureAngle, pressureGradient, pressureMin, pressureMax, velocitySize, velocityAngle, velocityGradient, velocityMin, velocityMax, dynamicsMinSize, dynamicsMinAngle, dynamicsMaxAngle, dynamicsDither, dynamicsCurve, symmetry, symmetryX, symmetryY, tilemapMode, shapeFillMode, cornerRadius, selectionCornerRadius, cornerRadiusLinked, lineWidth, curvePixelPerfect, bucketFillMode, bucketTolerance, bucketCloseGap, bucketDiagonal, bucketStopAtGrid, bucketPattern, wandFillMode, wandTolerance, wandDiagonal, wandStopAtGrid, sprayRate, scatterX, scatterY, scatterCount, blurStrength, jumbleStrength, dodgeBurnStrength, dodgeBurnHueShift, ditherPattern, ditherDensity, gradientType, gradientDithering, gradientSnap, gradientColors, gradientStops, eyedropperSource, tileIndex, tileFlipH, tileFlipV, tileRotate90, tilePlace, isoShape, isoWidth, isoDepth, isoHeight, isoBevel, isoCap, isoStyle, isoHiddenEdges, isoDirection, isoAutoShade, isoColors }. Colors are { r, g, b, a } tables; symmetry is an array of axes; customBrush is { width, height, mask (flat 0/1 list) } or nil. Change it with app.setContext.

Returns (table): Context table.

#### `app.setContext(props)` — changes
Changes the editing context — the current colors, brush, symmetry, tilemap mode and tool options. Draw commands use them for options they aren't given, except symmetry, which is only stored for the UI (and readable via app.getContext) and is never applied to a command unless you pass it. Shared with the GUI: the toolbar shows the change, and it persists after the script ends. Not an undoable edit.

- `props` (table) — Omitted keys are unchanged.
  - `foregroundColor` (color ("#rgb", "#rrggbb[aa]" or { r, g, b, a })) — The paint color: every draw command's `color`, and the gradient's start color.
  - `backgroundColor` (color ("#rgb", "#rrggbb[aa]" or { r, g, b, a })) — The secondary color: the gradient's end color, and what swapColors exchanges.
  - `brushSize` (integer 1–64) — Brush size in pixels for the built-in shapes (ignored by a custom brush). Also sets the spray radius (2x the size).
  - `brushShape` (BrushShape: "circle" | "square" | "line" | "diamond" | "cross" | "x" | "star" | "horizontal" | "custom") — "line" is a 1px line tilted by `brushAngle`; "square" is rotated by it; "circle", "diamond", "cross", "x" and "star" ignore it; "horizontal" is a line at angle 0 that ignores it; "custom" paints `customBrush`.
  - `brushAngle` (integer 0–180) — Brush angle in degrees (0-180): tilts the "line" brush and rotates the "square" brush. Ignored by other shapes.
  - `customBrush` ({ width, height, mask } with mask a flat list of 0/1, or false to clear) — The mask a custom brush paints: { rows = { ".#.", "###", ".#." } } or { width, height, mask } with mask a flat 0/1 list. Normally set with app.useBrush(name) from a brush defined with app.defineBrush. Without one, a custom brush paints a 1px dot.
  - `pixelPerfect` (boolean) — Removes doubled corner steps from freehand strokes (any brush size); the brush is stamped along the corrected path.
  - `eraserRightClick` (EraserRightClick: "background" | "replace") — Eraser right button: "background" paints the background color everywhere it touches, "replace" turns only foreground-colored pixels into the background color (Aseprite).
  - `ink` (Ink: "copy" | "simple" | "lock-alpha" | "shading") — How paint (strokes, spray, shapes, lines, polygon, contour, bucket, gradient, fillSelection) combines with existing pixels: "copy" replaces them (the default), "simple" alpha-composites, "lock-alpha" recolors only visible pixels, "shading" steps pixels along `shades`.
  - `shades` (a list of colors ("#rrggbb[aa]" or { r, g, b, a }), in order) — The ramp the shading ink steps along, in order: the editor's Shades box (or the selected palette range). Draw commands use it when ink is shading.
  - `stabilizer` (integer 0–64) — Stabilizer strength for freehand strokes: each point is averaged with the previous N points, smoothing wobble (the stroke lags the cursor). 0 = off.
  - `pressureSize` (boolean) — Let pen pressure (a mouse counts as full pressure) drive the brush size, from dynamicsMinSize up to brushSize.
  - `pressureAngle` (boolean) — Let pen pressure (a mouse counts as full pressure) drive the brush angle, from dynamicsMinAngle to dynamicsMaxAngle.
  - `pressureGradient` (boolean) — Let pen pressure (a mouse counts as full pressure) blend the color from foregroundColor to backgroundColor along the stroke.
  - `pressureMin` (integer 0–100) — Reading (percent) of the pressure sensor that maps to the low end. Greater than pressureMax inverts the mapping.
  - `pressureMax` (integer 0–100) — Reading (percent) of the pressure sensor that maps to the high end.
  - `velocitySize` (boolean) — Let pointer speed drive the brush size, from dynamicsMinSize up to brushSize.
  - `velocityAngle` (boolean) — Let pointer speed drive the brush angle, from dynamicsMinAngle to dynamicsMaxAngle.
  - `velocityGradient` (boolean) — Let pointer speed blend the color from foregroundColor to backgroundColor along the stroke.
  - `velocityMin` (integer 0–100) — Reading (percent) of the velocity sensor that maps to the low end. Greater than velocityMax inverts the mapping.
  - `velocityMax` (integer 0–100) — Reading (percent) of the velocity sensor that maps to the high end.
  - `dynamicsMinSize` (integer 1–64) — Brush size at the low end of a sensor mapped to size (the high end is brushSize).
  - `dynamicsMinAngle` (integer 0–180) — Brush angle at the low end of a sensor mapped to angle.
  - `dynamicsMaxAngle` (integer 0–180) — Brush angle at the high end of a sensor mapped to angle.
  - `dynamicsDither` (boolean) — Gradient dynamics pick foregroundColor or backgroundColor per pixel (ordered dither) instead of blending. Indexed sprites snap blends to the nearest palette color.
  - `dynamicsCurve` (integer 25–400) — Sensitivity curve in percent: the sensor value is raised to curve/100 (100 = linear, above 100 needs more pressure/speed to take effect).
  - `symmetry` (list of SymmetryAxis: "horizontal" | "vertical" | "diagonal" | "antidiagonal") — The active sprite's symmetry setting (each sprite keeps its own, like its axis position): mirror axes through the symmetry center. Readable information only — draw commands do not apply it unless you pass symmetry = app.getContext().symmetry. Empty = off; several axes combine (horizontal + vertical = 4-way).
  - `symmetryX` (a number (multiple of 0.5), or false to re-center) — Where the vertical symmetry axis (and the point both diagonals cross) sits: pixels from the canvas's left edge, a multiple of 0.5 (whole = between pixels, x.5 = through a pixel's middle). nil = centered. Like symmetry, readable information only: pass symmetryX = app.getContext().symmetryX to a draw command to follow it. Set false to re-center.
  - `symmetryY` (a number (multiple of 0.5), or false to re-center) — Where the horizontal symmetry axis (and the diagonals' crossing) sits: pixels from the canvas's top edge, a multiple of 0.5. nil = centered. Set false to re-center.
  - `tilemapMode` (TilemapEditMode: "tiles" | "pixels-edit" | "pixels-auto") — How pixel paint treats a tilemap layer: "pixels-auto" gives each painted cell its own tile, "pixels-edit" edits the shared tile in place (every placement updates), "tiles" allows only whole-tile stamping.
  - `shapeFillMode` (FillMode: "outline" | "filled") — Rectangles, ellipses, polygons and closed curves: outline or filled.
  - `cornerRadius` (an integer 0–1024 for every corner, or a list of four { topLeft, topRight, bottomRight, bottomLeft }) — Rectangle: corner radii in pixels, clockwise from the top-left (0 = a square corner), each clamped to half the smaller side.
  - `selectionCornerRadius` (an integer 0–1024 for every corner, or a list of four { topLeft, topRight, bottomRight, bottomLeft }) — Rectangular marquee: corner radii in pixels, clockwise from the top-left (0 = a square corner).
  - `cornerRadiusLinked` (boolean) — The tool options bar edits all four corner radii together (one Radius field) instead of one field per corner.
  - `lineWidth` (integer 1–64) — Line and Curve tools: thickness in pixels (1 = a hard 1px line); wider lines get round ends.
  - `curvePixelPerfect` (boolean) — Curve tool: remove the L-shaped corners a 1px curve picks up, for clean pixel-art lines.
  - `bucketFillMode` (BucketFillMode: "contiguous" | "global") — Flood fill: only the connected region, or every matching pixel.
  - `bucketTolerance` (integer 0–255) — Flood fill: the largest per-channel difference that still counts as the same color.
  - `bucketCloseGap` (integer 0–5) — Flood fill (contiguous): treat gaps in the outline up to this many pixels wide as closed, so the fill doesn't leak through them. 0 = off.
  - `bucketDiagonal` (boolean) — Flood fill (contiguous): also spread to diagonal neighbours (8-connected), so the region leaks through 1px diagonal lines.
  - `bucketStopAtGrid` (boolean) — Flood fill: confine the region to the grid cell the click lands in.
  - `bucketPattern` (FillPattern: "solid" | "checker" | "dither25" | "dither75" | "hstripes" | "vstripes" | "diagonal" | "grid" | "dots" | "bricks") — Flood fill: paint a repeating two-color pattern (the fill color and the other of foreground/background) instead of a solid color. "solid" = no pattern.
  - `wandFillMode` (BucketFillMode: "contiguous" | "global") — Magic wand: only the connected region, or every matching pixel. Separate from the flood fill's bucketFillMode.
  - `wandTolerance` (integer 0–255) — Magic wand: the largest per-channel difference that still counts as the same color. Separate from the flood fill's bucketTolerance.
  - `wandDiagonal` (boolean) — Magic wand (contiguous): also spread to diagonal neighbours (8-connected), so the region leaks through 1px diagonal lines.
  - `wandStopAtGrid` (boolean) — Magic wand: confine the region to the grid cell the click lands in.
  - `sprayRate` (integer 1–64) — Spray: dots per point.
  - `scatterX` (integer 0–64) — Scatter: how far each stamp can land left or right of the path, in pixels.
  - `scatterY` (integer 0–64) — Scatter: how far each stamp can land above or below the path, in pixels.
  - `scatterCount` (integer 1–16) — Scatter: stamps placed at each step along the path.
  - `blurStrength` (integer 1–4) — Blur: neighborhood radius in pixels.
  - `jumbleStrength` (integer 0–100) — Jumble: percent chance each touched pixel is scrambled.
  - `dodgeBurnStrength` (integer 1–100) — Dodge/burn: how far each touched pixel's OKLCH lightness moves (100 = half of black-to-white).
  - `dodgeBurnHueShift` (integer 0–60) — Dodge/burn: degrees each touched pixel's OKLCH hue turns toward warm yellow (dodge) or cool blue (burn), never past it; 0 keeps the hue.
  - `ditherPattern` (DitherPattern: "bayer2" | "bayer4" | "bayer8" | "dots" | "lines-h" | "lines-v" | "diagonal" | "noise") — Dither brush: the ordered pattern it paints through. Patterns tile from the sprite's top-left corner, so strokes line up.
  - `ditherDensity` (integer 0–100) — Dither brush: the share of the pattern's pixels it paints, in percent (50 with bayer2 is a checkerboard).
  - `gradientType` (GradientType: "linear" | "radial") — Gradient: a straight ramp between the points, or radiating from the start point.
  - `gradientDithering` (GradientDithering: "none" | "bayer2" | "bayer4" | "bayer8" | "dots" | "lines-h" | "lines-v" | "diagonal" | "noise") — Gradient: the ordered-dithering pattern (none = a smooth ramp).
  - `gradientSnap` (GradientSnap: "free" | "palette") — Gradient: free blends, or only palette colors (each pixel the nearest palette color; dithering steps between neighbouring palette colors).
  - `gradientColors` (GradientColors: "fg-bg" | "stops") — Gradient: run from the foreground to the background color, or along gradientStops ("stops"; fewer than two stops falls back to foreground to background).
  - `gradientStops` (a list of { color, position } (position 0-1, in order), or a list of colors spread evenly) — Gradient: the multi-stop ramp from the start point, as { color, position } entries (position 0-1, in order; two at one position make a hard edge). A plain list of colors is spread evenly. Used when gradientColors is "stops"; the editor's Stops bar edits it.
  - `eyedropperSource` (EyedropperSource: "composite" | "layer") — Eyedropper: sample what the canvas shows, or only the active layer.
  - `tileIndex` (integer ≥ 0) — Tile stamp: the 1-based tile to place (0 = the empty tile).
  - `tileFlipH` (boolean) — Tile stamp: flip placed tiles horizontally.
  - `tileFlipV` (boolean) — Tile stamp: flip placed tiles vertically.
  - `tileRotate90` (boolean) — Tile stamp: rotate placed tiles 90° clockwise.
  - `tilePlace` (boolean) — Place tiles: on a tilemap layer the pencil, eraser, line, shape tools and bucket place the tile stamp's tile (erase it, for the eraser) on the cells they cover instead of painting pixels.
  - `isoShape` (IsoShape: "box" | "ramp" | "stairs" | "pyramid" | "prism" | "cylinder" | "cone" | "sphere" | "dome") — Iso Shape tool: the solid it draws.
  - `isoWidth` (integer 1–1024) — Iso Shape tool: footprint along x (down-right), in iso units (one row of the edge staircase each).
  - `isoDepth` (integer 1–1024) — Iso Shape tool: footprint along y (down-left), in iso units.
  - `isoHeight` (integer 0–1024) — Iso Shape tool: height in pixels (0 = flat).
  - `isoBevel` (integer 0–1024) — Iso Shape tool: boxes only, how many pixels the top edges are chamfered (0 = square).
  - `isoCap` (integer 2–4) — Iso Shape tool: the flat run at the top and bottom vertices, 2 (even), 3 (odd) or 4 (multiples of four). Also the W / D drag step (2 units at cap 4).
  - `isoStyle` (IsoShapeStyle: "filled" | "outline" | "filled-outline") — Iso Shape tool: faces, outline, or both.
  - `isoHiddenEdges` (boolean) — Iso Shape tool: also draw the edges behind the solid.
  - `isoDirection` (IsoDirection: "+x" | "-x" | "+y" | "-y") — Iso Shape tool: which way a ramp or stairs descend, or a prism's slopes face.
  - `isoAutoShade` (boolean) — Iso Shape tool: derive the five colors from the foreground color along `shades` (true), or use isoColors (false).
  - `isoColors` (a list of colors ("#rrggbb[aa]" or { r, g, b, a }), in order) — Iso Shape tool: the colors used when isoAutoShade is off, in order outline, inner edge, top, left, right.

Returns nothing.

#### `app.swapColors()` — changes
Swaps the foreground and background colors (the GUI's X).

Returns nothing.
