API de scripting

Los scripts Lua controlan el mismo motor sobre el que corre el editor: cada herramienta, capa, fotograma, tile y selección con los que una persona puede trabajar, legibles y modificables desde código, con pantalla o sin ella. Esta referencia se genera a partir del propio motor, así que siempre coincide con lo que hace la app: 251 funciones (35 lecturas, 158 cambios, 58 utilidades para imágenes, números aleatorios, cálculo de color y diálogos de script).

Todas las funciones están en la tabla global app. Las llamadas son síncronas desde el punto de vista del script. print(...) escribe en la consola del script, y app.config contiene los valores del formulario de configuración del script (siempre definida, vacía si no hay formulario). Los colores son cadenas "#rgb", "#rrggbb" / "#rrggbbaa" o tablas { r, g, b, a }. Las coordenadas son píxeles enteros del sprite con (0, 0) arriba a la izquierda. Los ids de capas, fotogramas, etiquetas y slices son cadenas. Las tablas de Lua empiezan en 1, y una lista devuelta de números 0/1 o RGBA va por filas.

  • Empieza con app.describe(). Una sola llamada devuelve la estructura completa del documento: capas, fotogramas, celdas, etiquetas, slices, selección y contexto de edición.
  • Crear devuelve un id. app.addLayer, app.addFrame, app.addTag y similares devuelven lo que crearon, válido tras deshacer y rehacer.
  • La selección y la simetría son opcionales. Si omites un color o un pincel, el contexto de edición lo completa. La selección y la simetría son opcionales: pasa respectSelection = true y symmetry = app.getContext().symmetry.
  • Una ejecución, un deshacer. Todo lo que cambia un script es un único paso de deshacer. Las capas bloqueadas se rechazan.
  • Sin límite de tiempo. Cualquier ejecución se puede pausar (incluso a mitad de un bucle), reanudar, detener, o detener y revertir.
  • Usa app.random, no math.random. app.random.new(seed) es un generador con semilla: la misma semilla da el mismo resultado en cada ejecución (y al rehacer), así que los scripts deben tomar una semilla de app.config y preferirla a math.random. app.random.hash(x, y, seed) genera ruido por píxel. pairs() también recorre las claves de una tabla en el mismo orden en cada ejecución, así que iterar una tabla de colores no cambia el arte.
  • Los bucles de píxeles pasan por una Image. app.getImage, luego img:getPixel / img:setPixel tantas veces como quieras, y después un solo app.putImage. Cada llamada app.* es un viaje al editor; los métodos de una Image no lo son.
  • Usa app.color, no análisis y mezcla de hex hechos a mano. app.color.mix, adjust, ramp, shades, nearest y contrast trabajan en un espacio perceptual (OKLab) y ajustan a sRGB; analizar "#rrggbb" con string.sub y promediar canales da resultados apagados.
  • En un entorno aislado. Sin red, archivos ni carga de código; un script solo puede tocar el sprite abierto. Cada ejecución tiene un presupuesto de memoria (sus Images, sus datos Lua, lo que añade al documento y al historial de deshacer): al superarlo, el script se detiene con un error y lo que hizo hasta entonces queda como un único paso de deshacer. app.apiVersion indica a un script en qué versión de esta API se ejecuta.

Secciones

  • Grupos de opciones: Las opciones de pintura y de pincel que comparten las funciones de dibujo, definidas una sola vez.
  • Documento: El sprite en conjunto: empieza aquí con app.describe(), y luego tamaño, recorte, rotación y modo de color. (15 funciones)
  • Dibujo: Las herramientas del editor como comandos: las herramientas de la interfaz envían exactamente estos. El color, el pincel y las opciones de herramienta que omitas vienen del contexto de edición. Pintar ignora la selección y la simetría salvo que pases respectSelection = true y symmetry = app.getContext().symmetry. (24 funciones)
  • Correcciones: Las correcciones de color y los efectos de color del menú Filtro, cada uno un paso de deshacer sobre las celdas de una capa en los fotogramas que indiques. Ignoran la selección salvo que pases respectSelection = true, y nunca tocan los píxeles totalmente transparentes. En sprites indexados, indexedMode elige entre ajustar los píxeles recoloreados a la entrada de paleta más cercana ("remap") y editar las entradas de paleta que usan las celdas ("palette"). (16 funciones)
  • Imágenes: La forma rápida de trabajar píxel por píxel. app.getImage lee una celda (o parte de ella) en una Image, un búfer de píxeles que vive dentro del script: img:getPixel e img:setPixel nunca salen del script, así que un bucle sobre todos los píxeles de una celda de 512 x 512 tarda alrededor de una décima de segundo. app.putImage la escribe de vuelta como un único cambio, sin importar cuántos píxeles hayas establecido. Un píxel es un entero empaquetado (app.pixelColor.rgba(r, g, b, a), como en Aseprite); setPixel también acepta "#rrggbb[aa]" y { r, g, b, a } (alfa es 255 por defecto). En sprites indexados, img:getIndex e img:setIndex trabajan con índices de paleta, de modo que los colores duplicados se mantienen separados. El patrón habitual: local img = app.getImage(layer, frame); for y = 0, img.height - 1 do for x = 0, img.width - 1 do img:setPixel(x, y, ...) end end; app.putImage(layer, frame, img). (17 funciones)
  • Píxeles: Lectura y escritura de píxeles como listas RGBA planas (construidas sobre Images; nunca recortadas por la selección ni reflejadas), rellenos y volteos de la selección completa, y el cuentagotas. (7 funciones)
  • Selección: Las formas de selección se combinan con la selección actual (reemplazar, añadir, restar, intersecar). La máscara de selección se puede leer y escribir. (19 funciones)
  • Capas: Crea, organiza y configura capas. Los grupos son carpetas de capas: el parentId de una capa nombra su grupo (nil en el nivel superior) y las posiciones de app.moveLayer cuentan dentro de un grupo (0 = abajo). Ocultar o bloquear un grupo oculta o bloquea todo lo que contiene. Un grupo con opacidad total y modo de mezcla "normal" es de traspaso (sus capas se mezclan directamente con lo de abajo) salvo que tenga activada su marca isolated; un grupo aislado, o con cualquier otra opacidad o modo, compone primero sus capas entre sí. (25 funciones)
  • Fotogramas y etiquetas: La línea de tiempo: los fotogramas, sus duraciones y las etiquetas de animación. (25 funciones)
  • Celdas: Una celda es la imagen de una capa en un fotograma. Muévelas, bórralas y vincúlalas en bloques. (9 funciones)
  • Tilemaps: Las capas de tilemap colocan en una cuadrícula tiles de su propio tileset. Los tiles se numeran desde 1 (0 es el tile vacío). (19 funciones)
  • Paleta: La paleta del sprite. (21 funciones)
  • Slices: Rectángulos con nombre, p. ej. para regiones de exportación o hitboxes. Un slice también puede ser un 9-slice (un rectángulo central) y llevar un punto de pivote; ambos son relativos a la esquina superior izquierda del slice, como en Aseprite, y se mueven con él cuando el lienzo cambia de tamaño, se recorta o se gira. (5 funciones)
  • Pinceles: Define tus propios pinceles por nombre y pinta con ellos. Viven solo en el motor durante la sesión: no están en el documento, no se pueden deshacer, no se guardan y son independientes de la biblioteca de pinceles del editor. (6 funciones)
  • Contexto de edición: Los colores, el pincel, la simetría y las opciones de herramienta actuales, compartidos con la barra de herramientas del editor. Los comandos de dibujo los usan para los colores, el pincel y las opciones de herramienta que no se les pasan; la simetría es solo informativa y se aplica únicamente cuando la pasas. (3 funciones)
  • Aleatorio: Números aleatorios con semilla, calculados dentro del script (sin ida y vuelta por cada llamada). La misma semilla da los mismos resultados, así que un script se puede volver a ejecutar, deshacer y rehacer, o compartir, y verse idéntico. Prefiérelos a math.random, que cambia en cada ejecución. Los generadores son objetos: llama a sus métodos con dos puntos (rng:int(1, 6)). (11 funciones)
  • Color: Matemática del color sin analizar hexadecimales a mano ni mezclar RGB a mano. Los colores de entrada son cadenas "#rrggbb" / "#rrggbbaa" o tablas { r, g, b, a } (0-255, a opcional); los colores de salida son tablas { r, g, b, a } salvo que el nombre indique hex. Mezclar y ajustar usan OKLab por defecto, un espacio perceptual en el que pasos iguales se ven iguales; `space` puede ser "oklab", "oklch", "rgb" o "hsl". Los resultados se limitan a sRGB reduciendo la croma, así que el tono y la luminosidad se mantienen. Las listas (ramp, shades) se construyen en una sola llamada. (11 funciones)
  • Diálogos y comandos: Interfaz de scripts, modelada sobre la de Aseprite: Dialog{ title = ... } construye una ventana a partir de widgets (label, entry, number, slider, check, radio, combobox, color, shades, button, separator, file) y plugin:newCommand añade comandos a los menús, a la paleta de comandos y al editor de Atajos de teclado. El editor dibuja la ventana, solo con texto, con una barra de título que nombra el script y lo marca como "script". Los callbacks (onclick, onchange, onclose) se ejecutan en el script, de uno en uno, cada uno como un solo paso de deshacer; un script con un diálogo abierto sigue vivo, inactivo, mientras el usuario sigue dibujando, y detenerlo cierra sus diálogos. No se admiten: widgets de lienzo ni dlg:repaint. (18 funciones)
  • Formularios de configuración: El formulario previo a la ejecución que declara un script: campos de número, texto, casilla, selección, color, pincel y paleta.
  • Ajustes del contexto: Los colores, el pincel y las opciones de herramienta que usan por defecto los comandos de dibujo, más el interruptor de simetría de la interfaz (solo informativo).
  • Tipos: Cada conjunto de valores con nombre (FillMode, BlendMode, SymmetryAxis, ...), con cada valor explicado.
  • Lectura del documento: Cómo lee un script cada parte del modelo del documento.
  • Comandos internos: Comandos del motor que los scripts no pueden llamar, y por qué.
  • Lo que queda en el editor: Lo que un script no puede alcanzar: zoom, paneles, reproducción, guardado.

En Markdown: scripting.md; toda la documentación en un solo archivo: llms-full.txt.