# Guide de script

Écris des scripts Lua qui dessinent et modifient tes sprites, exécute des scripts et des générateurs de la bibliothèque, et ajoute tes propres fenêtres et commandes de menu.

_Les raccourcis sont écrits pour Windows et Linux. Sur Mac, utilise ⌘ Cmd là où il est écrit Ctrl, et ⌥ Option pour Alt._

Les scripts sont des programmes Lua qui travaillent sur le sprite ouvert. Ils pilotent le même moteur
que l'éditeur : tout outil, calque, image, cel, étiquette, slice, tuile et entrée de palette que tu peux
modifier à la main, un script peut le modifier avec du code. Utilise-les pour générer des dessins
(arbres, rochers, textures, champs d'étoiles), pour répéter une modification fastidieuse, ou pour
ajouter tes propres commandes aux menus.

Tu débutes avec les scripts ? [Ton premier script](https://pxstud.io/fr/docs/scripting/first-script.md) t'accompagne pour en écrire un et
l'exécuter. Cette page couvre tout ce qui l'entoure.

## Le menu Scripts

| Élément | Ce qu'il fait |
| - | - |
| Scripts > Nouveau script... | Nomme un nouveau script et l'ouvre dans le panneau Scripts. |
| Scripts > Ouvrir mon script... | Liste tes scripts : choisis-en un pour l'ouvrir, ou renomme-le ou supprime-le. Les cinq derniers que tu as ouverts sont listés dans le menu en dessous. |
| Scripts > Parcourir la bibliothèque de scripts... | La bibliothèque de scripts : cherche, exécute, forke et ajoute un cœur aux scripts partagés, dont les générateurs officiels. Voir [La bibliothèque](https://pxstud.io/fr/docs/manual/guides/library.md). |
| Scripts > Commandes de scripts... | Installe des commandes de menu à partir de tes scripts ([plus bas](https://pxstud.io/fr/docs/scripting/guide.md#script-commands)). |
| Scripts > API de scripting | Ouvre la référence de l'[API de script](https://pxstud.io/fr/docs/scripting.md) dans un nouvel onglet. |

Chacun de ces éléments se trouve aussi dans la palette de commandes (`Ctrl+K`).

## Le panneau Scripts

Le panneau **Scripts** s'ouvre quand tu crées ou ouvres un script (dans les dispositions par défaut,
ancré à droite du canevas, pour que tu puisses regarder un script dessiner ; sur un téléphone, devant
lui). Affichage > Panneaux > Scripts l'affiche et le masque, et un rechargement rouvre le script que tu avais
ouvert (son dernier brouillon enregistré). Il comporte un éditeur de code avec coloration Lua, des
suggestions pour chaque fonction `app.` pendant que tu tapes, et une description quand tu en pointes une.
Sous le code, une zone de sortie montre ce que le script affiche et toute erreur.

![Le panneau Scripts montrant le code d'un script, avec sa barre d'outils en haut et sa sortie affichée en dessous](https://pxstud.io/scripting/images/first-script-panel.light.webp)

_Le panneau Scripts_

En haut, de gauche à droite :

- **Le nom du script.** Double-clique dessus pour renommer le script. Un `*` signale des modifications
  non enregistrées ; à côté, « brouillon » pour un script que tu n'as pas publié, ou la version que tu
  modifies (« v2 », « v2 · modifié »).
- **Privé** ou **Partagé** : qui peut voir le script dans la bibliothèque. Clique dessus pour changer.
- **Référence de l'API de scripts** (le livre) ouvre la référence dans un nouvel onglet.
- **Exécuter** (le bouton de lecture) exécute le script sur le sprite actif ; un script qui a un
  [formulaire de configuration](https://pxstud.io/fr/docs/scripting/guide.md#config-forms) demande d'abord ses valeurs. Pendant l'exécution, les
  commandes d'exécution prennent sa place ([plus bas](https://pxstud.io/fr/docs/scripting/guide.md#running-pausing-and-stopping)).
- **Enregistrer le brouillon** (la disquette) enregistre le script dans ce navigateur.
- **Publier** demande une note de version facultative, puis enregistre le script et le publie comme
  nouvelle version.
- **Paramètres du script** (les curseurs) ouvre les paramètres du script : ses étiquettes, qui peut le
  voir, son formulaire de configuration et ses versions publiées.
- **Masquer le panneau** ferme le panneau. Le script ouvert reste listé dans le menu Fichier, avec les
  sprites : choisis-y son nom pour afficher de nouveau le panneau.

Le script de quelqu'un d'autre (ouvert avec **Voir le code** dans la bibliothèque) est en lecture seule.
Sa barre d'outils propose **Forker** à la place d'Enregistrer le brouillon et de Publier : cela le copie
dans un nouveau script à toi, que tu peux modifier.

## Exécuter, mettre en pause et arrêter

Un script s'exécute sur le sprite que tu regardes, et tu le vois dessiner au fur et à mesure. Quelle que
soit l'ampleur de ses modifications, une exécution compte pour **une seule étape d'annulation** :
`Ctrl+Z` reprend toute l'exécution.

Les scripts n'ont **aucune limite de temps**. Pendant qu'un script s'exécute, ses commandes d'exécution te
permettent d'y mettre fin plus tôt :

| Commande | Ce qu'elle fait |
| - | - |
| **Pause** / **Reprendre** | Arrête le script là où il en est, même au milieu d'une boucle, et le fait continuer plus tard. |
| **Arrêter** | Termine le script et conserve ce qu'il a fait jusque-là. |
| **Arrêter et annuler** | Termine le script et annule tout ce qu'il a modifié. |

Dans le panneau Scripts, ce sont de petits boutons dans la barre d'outils. Un script exécuté depuis la
bibliothèque recouvre l'éditeur d'une fenêtre qui affiche son nom, sa sortie et les mêmes trois
commandes, jusqu'à ce qu'il se termine.

Quand un script échoue, la sortie affiche l'erreur ; dans le panneau, la ligne où il a échoué est mise
en évidence. Un script ne peut pas peindre sur un calque verrouillé : la commande est refusée et le
script s'arrête avec une erreur.

## Écrire des scripts

Chaque fonction se trouve dans la table `app`. L'[API de script](https://pxstud.io/fr/docs/scripting.md) documente chacune
d'elles, générée à partir de l'éditeur lui-même, en sections :

- [Dessin](https://pxstud.io/fr/docs/scripting/drawing.md) : les outils sous forme de commandes (`app.drawLine`,
  `app.floodFill`, `app.drawIsoShape`...), [Images](https://pxstud.io/fr/docs/scripting/images.md) pour travailler pixel par
  pixel, et [Pixels](https://pxstud.io/fr/docs/scripting/pixels.md) pour les listes de pixels à plat, les remplissages et la
  pipette ;
- [Document](https://pxstud.io/fr/docs/scripting/document.md), [Calques](https://pxstud.io/fr/docs/scripting/layers.md),
  [Images d'animation](https://pxstud.io/fr/docs/scripting/frames.md), [Cels](https://pxstud.io/fr/docs/scripting/cels.md),
  [Sélection](https://pxstud.io/fr/docs/scripting/selection.md), [Slices](https://pxstud.io/fr/docs/scripting/slices.md) et
  [Tilemaps](https://pxstud.io/fr/docs/scripting/tilemaps.md) ;
- [Palette](https://pxstud.io/fr/docs/scripting/palette.md), [Ajustements](https://pxstud.io/fr/docs/scripting/adjustments.md) et
  [Pinceaux](https://pxstud.io/fr/docs/scripting/brushes.md) ;
- des utilitaires : les calculs de [couleur](https://pxstud.io/fr/docs/scripting/color.md), les nombres [aléatoires](https://pxstud.io/fr/docs/scripting/random.md)
  avec graine, et le [contexte d'édition](https://pxstud.io/fr/docs/scripting/context.md) (les couleurs, le pinceau et les
  options d'outil actuels).

Quelques points à connaître :

- **Commence par `print(app.describe())`.** `app.describe()` renvoie toute la structure du sprite :
  calques, images, cels, étiquettes, slices, la sélection et les réglages actuels.
- **Les réglages que tu omets viennent de l'éditeur.** Une commande de dessin sans couleur utilise la
  couleur de premier plan ; sans pinceau, le pinceau actuel ; et ainsi de suite pour chaque option
  d'outil.
- **La sélection et la symétrie ne s'appliquent que si tu le demandes.** Passe `respectSelection = true`
  pour continuer à peindre à l'intérieur de la sélection, et `symmetry = app.getContext().symmetry`
  pour la refléter.
- **Travaille pixel par pixel dans une Image.** `app.getImage(layer, frame)` lit un cel dans une Image qui
  vit à l'intérieur du script ; `img:getPixel` et `img:setPixel` sont peu coûteux, donc boucle sur autant
  de pixels que tu veux, puis réécris le tout en une fois avec `app.putImage(layer, frame, img)`. Chaque
  appel `app.*` est un aller-retour vers l'éditeur, alors que les méthodes d'une Image n'en sont pas. Sur
  les sprites indexés, `img:getIndex` et `img:setIndex` travaillent avec les indices de palette.
- **Utilise `app.random` pour l'aléatoire.** Un générateur créé avec `app.random.new(seed)` donne les
  mêmes nombres pour la même graine, donc une exécution peut être répétée à l'identique. `pairs()`
  parcourt aussi les clés d'une table dans le même ordre à chaque exécution.
- **Utilise `app.color` pour les calculs de couleur.** Les mélanges, les rampes et les teintes sont
  calculés dans un espace colorimétrique perceptuel, ce qui est plus joli que de faire la moyenne de
  valeurs hexadécimales.
- **Affiche pour vérifier.** `print(...)` écrit dans la zone de sortie ; les tables s'affichent en
  entier.

Par exemple, ceci disperse des étoiles sur un nouveau calque ; change la graine pour un autre ciel :

```lua
local layer = app.addLayer("Stars")
local frame = app.getActiveFrameId()

local rng = app.random.new(42)                        -- même graine, mêmes étoiles
local colors = app.color.ramp({ "#5a6b9e", "#ffffff" }, 4)

local img = app.getImage(layer, frame)                -- les pixels du calque, à l'intérieur du script
for i = 1, img.width * img.height // 40 do
  img:setPixel(rng:int(0, img.width - 1), rng:int(0, img.height - 1), rng:pick(colors))
end
app.putImage(layer, frame, img)                       -- réécrit en une seule modification
```

## Formulaires de configuration

Un script peut demander des réglages avant de s'exécuter : quand tu choisis **Exécuter** (dans la
bibliothèque, ou dans le panneau Scripts), un formulaire s'ouvre avec ses champs (nombres, texte, cases
à cocher, choix, couleurs, et un pinceau ou une palette de tes propres bibliothèques), et le script lit
ce que tu as saisi dans la table `app.config`. Les champs peuvent s'afficher ou se masquer selon les
choix précédents. **Aléatoire** tire de nouvelles valeurs dans les plages choisies par l'auteur du
script, pour des variations rapides. Les générateurs officiels fonctionnent tous ainsi.

Pour donner un formulaire à l'un de tes scripts, écris-le en JSON dans **Formulaire de configuration**
dans les paramètres du script, sous la forme décrite par la référence des
[formulaires de configuration](https://pxstud.io/fr/docs/scripting/config-forms.md) ; les paramètres t'indiquent ce qui ne va
pas avant l'enregistrement. Le formulaire fait partie du brouillon et de chaque version publiée. Un
script devrait quand même lire chaque champ comme facultatif et se rabattre sur ses propres valeurs par
défaut. Pour une saisie pendant l'exécution d'un script, ouvre plutôt une fenêtre de script.

## Fenêtres de script

Un script peut ouvrir sa propre fenêtre avec `Dialog{}`, construite comme les scripts Aseprite les
construisent : étiquettes, zones de texte et de nombre, curseurs, cases à cocher, boutons radio, listes
déroulantes, champs de couleur, rangées d'échantillons de couleur, boutons et un sélecteur de fichier
(petits fichiers texte uniquement).

```lua
local dlg = Dialog{ title = "Quick Fill" }
dlg:color{ id = "paint", label = "Color", color = "#3a8f4a" }
dlg:button{ id = "fill", text = "Fill layer", onclick = function()
  local layer, frame = app.getActiveLayerId(), app.getActiveFrameId()
  app.floodFill(layer, frame, 0, 0, { color = dlg.data.paint })
end }
dlg:show{ wait = false }
```

- `dlg:show{ wait = false }` ouvre une **fenêtre flottante** et le script attend, inactif, pendant que tu
  continues à dessiner ; chaque appui sur un bouton ou changement auquel il réagit est sa propre étape
  d'annulation. Sans `wait = false`, la fenêtre est modale : l'éditeur est verrouillé jusqu'à ce que tu
  la fermes.
- La barre de titre de la fenêtre nomme le script et la marque comme celle d'un script, et tout ce
  qu'elle contient est du texte brut, donc un script ne peut pas faire passer sa fenêtre pour une partie
  de l'éditeur.
- Fermer la fenêtre met fin au script ; arrêter le script ferme ses fenêtres.

La référence [Boîtes de dialogue et commandes](https://pxstud.io/fr/docs/scripting/dialogs.md) détaille chaque widget et ses
options.

## Commandes de script

Un script peut ajouter des **commandes** aux menus de l'éditeur, comme le fait un plugin Aseprite. Définis
une fonction `init(plugin)` qui les enregistre avec `plugin:newCommand` :

```lua
local function mirror()
  app.flip("horizontal", app.getActiveLayerId())
end

function init(plugin)
  plugin:newCommand{ id = "mirror", title = "Mirror Layer", group = "layer", onclick = mirror }
end
```

Enregistre le script, puis choisis Scripts > Commandes de scripts... et appuie sur **Installer** à côté de lui. La
commande apparaît alors :

- dans le menu que nomme son `group` (`file`, `file_import`, `edit`, `edit_transform`, `edit_fx`,
  `edit_adjustments`, `sprite`, `layer`, `frame`, `select` ou `view`), affichée avec le nom du script ;
  sans groupe, sous Scripts, dans un sous-menu portant le nom du script ;
- dans la palette de commandes ;
- dans Réglages > Raccourcis clavier..., où tu peux lui donner un raccourci.

Exécuter la commande exécute ton script enregistré puis le `onclick` de la commande, en une seule étape
d'annulation. Après avoir changé les commandes qu'un script enregistre, appuie sur **Réinstaller** ;
**Retirer** les enlève des menus. Un script peut ajouter jusqu'à 32 commandes. Les commandes installées
sont conservées dans ce navigateur.

Pour installer des commandes à partir du script de quelqu'un d'autre, forke-le d'abord dans tes scripts.

## Enregistrer et publier

Tes scripts sont enregistrés dans ce navigateur, comme tes sprites, et fonctionnent hors ligne. Avec
[Sync](https://pxstud.io/fr/docs/manual/concepts/how-work-is-organized.md#where-things-are-kept), ils sont aussi conservés dans ton
compte et sur tes autres appareils.

**Publier** partage un script dans la bibliothèque de scripts. Chaque script commence **Privé**, donc toi
seul peux le voir ; choisis **Partagé dans la bibliothèque** dans ses paramètres (**Paramètres du
script**, ou le badge Privé) pour le lister. Ensuite :

- **Enregistrer le brouillon** garde tes modifications privées. Les personnes qui utilisent la
  bibliothèque obtiennent toujours ta dernière version publiée, jamais le brouillon.
- **Publier** enregistre le brouillon et en fait la version numérotée suivante, avec la note de version
  que tu tapes (affichée dans l'historique des versions). Les versions publiées ne changent jamais ;
  publie de nouveau pour en créer une nouvelle.
- Les paramètres du script listent chaque version publiée. **Voir le code** ouvre une ancienne version en
  lecture seule, et **Restaurer dans mon brouillon** la copie dans ton brouillon.
- Un script peut avoir jusqu'à 3 étiquettes, qui aident les gens à le trouver dans la bibliothèque.

Publier demande un compte avec Sync sur pxstud.io. Exécuter, forker et ajouter un cœur aux scripts (avec
un compte gratuit) est décrit dans [La bibliothèque](https://pxstud.io/fr/docs/manual/guides/library.md).

## Ce que les scripts ne peuvent pas faire

Les scripts sont isolés dans un bac à sable, donc exécuter un script écrit par quelqu'un d'autre est sans
danger :

- **Pas de réseau, de fichiers ni de chargement de code.** Un script ne peut atteindre ni Internet ni tes
  fichiers (à part un fichier texte que tu choisis dans sa fenêtre), et ne peut pas charger d'autre code.
  Les bibliothèques `io`, `os` et `debug` de Lua ne sont pas là ; `string`, `math`, `table`, `utf8` et
  `coroutine` y sont.

- **Seulement le sprite ouvert.** Un script modifie le sprite sur lequel tu l'as exécuté, en une seule
  étape d'annulation. Il ne peut ni ouvrir, enregistrer, exporter, fermer ou supprimer des sprites, ni
  utiliser le presse-papiers, ni changer la vue et les panneaux.

- **Tes bibliothèques seulement quand tu y choisis.** Un script ne voit l'un de tes pinceaux ou l'une de
  tes palettes enregistrés que si son formulaire de configuration le demande et que tu le choisis.

- **Un budget de mémoire.** Une exécution ne peut pas utiliser plus d'une certaine quantité de mémoire :
  pour ses Images, ses données Lua, les pixels qu'elle ajoute au sprite et l'étape d'annulation qu'elle
  construit. Au-delà, le script est arrêté avec une erreur qui dit laquelle, et ce qu'il a fait
  jusque-là reste une seule étape d'annulation, donc un script qui s'emballe ne peut ni faire planter
  l'éditeur ni repousser tes étapes précédentes hors de l'historique des annulations.

Il n'y a pas de limite de temps ; un script qui s'emballe peut toujours être mis en pause ou arrêté.

## Les générateurs officiels

La bibliothèque de scripts de pxstud.io contient un ensemble de scripts officiels, marqués
**Officiel** : des générateurs de dégradés, de damiers, de remplissages de bruit, de murs de briques, de
pavés, de planches de bois, de textures d'herbe et d'eau, d'éclairs, de tornades, d'arcs-en-ciel, de
comètes, de galaxies, de planètes, d'étoiles, d'arbres, de buissons et de rochers. Connecte-toi avec un
compte gratuit, ouvre Scripts > Parcourir la bibliothèque de scripts..., choisis **Officiel**, et appuie sur **Exécuter** sur l'un
d'eux : remplis son formulaire (ou appuie sur **Aléatoire**) et il dessine sur ton sprite. Forke-en un
pour lire comment il est fait, ou pour le modifier.
