# pxstud.io Lua scripting API — Option groups

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

## Option groups
Sets of options shared by several functions, defined once here. A function's `opts` table says which groups it also takes — "also takes the Painting options" means every option below is accepted, with the same meaning and defaults, in addition to the function's own.

### Painting options (`paint`)
Taken by every command that paints pixels (the drawing functions and the stroke tools). Each is optional. By default a draw command ignores the selection and does not mirror, whatever the editor currently shows; opt in with respectSelection = true and symmetry = app.getContext().symmetry (or an axes list). tilemapMode is filled from the editing context.
Taken by: `app.blur`, `app.dodgeBurn`, `app.drawContour`, `app.drawCurve`, `app.drawEllipse`, `app.drawGradient`, `app.drawHexagon`, `app.drawIsoShape`, `app.drawLine`, `app.drawPolygon`, `app.drawRectangle`, `app.drawStar`, `app.drawStroke`, `app.drawTriangle`, `app.floodFill`, `app.jumble`, `app.scatter`, `app.spray`.

  - `respectSelection` (boolean; default false) — Pass true to paint only inside the current selection (read it with app.getSelection / app.isSelected). By default the selection is ignored.
  - `symmetry` (list of SymmetryAxis: "horizontal" | "vertical" | "diagonal" | "antidiagonal"; default none) — Mirror axes through the canvas center (or through symmetryX / symmetryY); combinations (horizontal + vertical) give 4-way symmetry. Default none: pass symmetry = app.getContext().symmetry to follow the editor's symmetry toggle, or an axes list such as { "vertical" }.
  - `symmetryX` (number ≥ 0; default the canvas center (width / 2)) — Where the vertical 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). Clamped to the canvas. Pass app.getContext().symmetryX to follow the editor's guide (nil there means centered).
  - `symmetryY` (number ≥ 0; default the canvas center (height / 2)) — Where the horizontal axis (and the diagonals' crossing) sits: pixels from the canvas's top edge, a multiple of 0.5. Clamped to the canvas.
  - `tilemapMode` (TilemapEditMode: "pixels-edit" | "pixels-auto"; default context.tilemapMode) — How a tilemap layer takes pixel paint: auto gives each painted cell its own tile, edit changes the shared tile in place. Ignored on image layers.

### Placement options (`tilePlace`)
Each is optional. By default tiles go on every given cell, whatever the editor shows. Mirrored cells get the mirrored tile: a vertical axis toggles flipH, a horizontal one flipV, a diagonal one transposes it (rotate90 plus a flip). A cell on an axis keeps the tile as placed.
Taken by: `app.fillTiles`, `app.stampTiles`.

  - `respectSelection` (boolean; default false) — Pass true to skip cells with no selected pixel (a fill also stops at them).
  - `symmetry` (list of SymmetryAxis: "horizontal" | "vertical" | "diagonal" | "antidiagonal"; default none) — Also place on the mirrored cells across these axes (and their combinations). Pass app.getContext().symmetry to follow the editor's toggle.
  - `symmetryX` (number ≥ 0; default the canvas center (width / 2)) — Where the vertical axis sits, in pixels from the canvas's left edge (a multiple of 0.5).
  - `symmetryY` (number ≥ 0; default the canvas center (height / 2)) — Where the horizontal axis sits, in pixels from the canvas's top edge (a multiple of 0.5).

### Brush options (`brush`)
Taken by the stroke tools (drawStroke, blur, jumble). Pass a built-in brush by size and shape, or a custom brush by name or inline.
Taken by: `app.blur`, `app.dodgeBurn`, `app.drawStroke`, `app.jumble`, `app.scatter`.

  - `brushSize` (integer 1–64; default context.brushSize) — Brush size in pixels.
  - `brushShape` (BrushShape: "circle" | "square" | "line" | "diamond" | "cross" | "x" | "star" | "horizontal"; default context.brushShape) — Brush shape. For a custom brush use `brush`.
  - `brushAngle` (integer 0–180; default context.brushAngle) — Brush angle in degrees: tilts the "line" shape (0 = horizontal, 90 = vertical) and rotates "square".
  - `brush` (brush name, or an inline { rows } / { width, height, mask }) — A custom brush: the name of one you defined with app.defineBrush, or an inline definition. Replaces brushSize, brushShape and brushAngle.

### Ink options (`ink`)
Taken by every painting command except erase: how the paint color combines with the pixels already there. Omitted options come from the editing context (ink, shades). With ink = "shading" the color is ignored and each touched pixel whose color is in `shades` moves one step along that list (once per command, however often the shape covers it).
Taken by: `app.drawContour`, `app.drawCurve`, `app.drawEllipse`, `app.drawGradient`, `app.drawHexagon`, `app.drawIsoShape`, `app.drawLine`, `app.drawPolygon`, `app.drawRectangle`, `app.drawStar`, `app.drawStroke`, `app.drawTriangle`, `app.floodFill`, `app.scatter`, `app.spray`.

  - `ink` (Ink: "copy" | "simple" | "lock-alpha" | "shading"; default context.ink) — copy replaces pixels, simple alpha-composites, lock-alpha recolors only visible pixels, shading steps colors along `shades`. Ignored by erase.
  - `shades` (a list of colors ("#rrggbb[aa]" or { r, g, b, a }), in ramp order; default context.shades) — The ramp shading steps along. A pixel whose color is not in the list is untouched; a pixel at the end of the list stays there.
  - `shadeReverse` (boolean; default false) — Shading steps backward in `shades` (the GUI's right mouse button) instead of forward.
