Skip to content

Story Editor — Guide d'utilisation

Le Story Editor est un plugin Godot intégré au projet. Il affiche un graphe visuel de toutes les scènes narratives définies dans les fichiers JSON, directement dans l'éditeur Godot — sans modifier le jeu en dehors des actions d'édition explicites.


Activation

  1. Dans Godot, ouvrir Projet → Paramètres du projet → Plugins
  2. Activer Story Editor
  3. Un onglet Story Editor apparaît en bas de l'éditeur (panneau inférieur, à côté de la console)

Prise en main

Une fois activé, voici les quatre actions de base pour démarrer :

  1. Cliquez sur Refresh — le graphe charge toutes les scènes des fichiers JSON du projet
  2. Cliquez sur un nœud — son contenu s'affiche dans le panneau de détail à droite ; les champs sont éditables directement
  3. Clic droit sur le fond du graphe — crée une nouvelle scène (ID, contact, fichier cible)
  4. Glissez un port de sortie vers un port d'entrée — connecte deux scènes (next)

Tout ce qui suit dans ce document détaille ces actions et les fonctionnalités avancées.


Interface

+--------------------------------------------------------------------------------------+
| [Refresh] [Reformater…] [Contacts] [Paramètres] [↩] [↪]   2/5 : scene_03            |
| [🚩 Flags] [📊 Analyser] [🗗]  [fr v]  [Tous v]  [Chercher...________] [<-] [->]    |
+-------------------------------------------+------------------------------------------+
|                                           |  scene_04                                |
|  [> ch1_intro] --> [scene_01] -------->   |  Contact  [Maeve              v]         |
|                         |                 |                                          |
|  [! orpheline]   [X scene_02]             |  Messages ----------------------         |
|                                           |                                          |
|  [~ scene_03] - - - trigger - - - ->      |   Bonjour !                   [x]        |
|                                           |   +-------------------------+            |
|                                           |   | Je t'ecris depuis le   |             |
|                                           |   | train.                 |             |
|                                           |   +-------------------------+            |
|                                           |   pause    [medium  v]                   |
|                                           |   requires [--      v]                   |
|                                           |                                          |
|                                           |  Choix  -------------------              |
|                                           |   C'est du spam -> [-- v] [x]            |
|                                           |   Je vous recois-> [-- v] [x]            |
|                                           |   [+ choix]                              |
+-------------------------------------------+------------------------------------------+

La toolbar est une seule rangée horizontale ; elle est représentée sur deux lignes ici pour la lisibilité.

Légende du graphe : [> id] = scène de départ · [! id] = isolée · [X id] = fin de parcours · [~ id] = saisie libre · - - -> = connexion trigger

Story Editor — graphe des scènes

  • Bouton Refresh : relit les fichiers JSON et reconstruit le graphe. À utiliser après chaque modification manuelle des fichiers de dialogue. Les actions d'édition depuis le graphe déclenchent un Refresh automatique.
  • Bouton Reformater… : ouvre une fenêtre de sélection avant toute écriture. Elle indique précisément quels fichiers de dialogues/ seront reformattés, y compris les éventuels fallbacks de la langue active. Voir Reformater des fichiers JSON.
  • Bouton Contacts : ouvre le panneau Contacts — une fenêtre flottante pour gérer la liste des personnages.
  • Bouton Paramètres : ouvre le panneau Paramètres — une fenêtre flottante pour les réglages globaux, les langues et l'écran de fin.
  • Bouton 🚩 Flags : ouvre le panneau Flags — une fenêtre flottante listant tous les flags du projet avec leurs scènes d'origine et d'utilisation.
  • Bouton 📊 Analyser : ouvre le panneau Analyser — une fenêtre flottante présentant une analyse complète du récit (accessibilité, flags inutilisés, boucles, personnages, durée indicative).
  • Boutons ↩ / ↪ : annuler / rétablir la dernière action (équivalents à Ctrl+Z / Ctrl+Y).
  • Bouton 🗗 : ouvre le Story Editor dans une fenêtre séparée — pratique sur un second écran. Un deuxième clic ramène la fenêtre existante au lieu d'en ouvrir une nouvelle. La fenêtre peut être mise en plein écran.
  • Filtre contact : dropdown listant tous les contacts du projet. Sélectionner un contact grise toutes les scènes des autres contacts à 20 % d'opacité — les connexions restent visibles pour garder le contexte global. Choisir « Tous » rétablit l'affichage normal. Le filtre est conservé après un Refresh.
  • Champ de recherche : saisir un texte et appuyer sur Entrée cherche d'abord dans les IDs de scène (exact → préfixe → sous-chaîne), puis dans le texte des messages et des choix. La recherche est insensible à la casse. Si plusieurs résultats correspondent, les boutons et (ou les touches fléchées / depuis le champ) permettent de naviguer entre eux ; le label de statut affiche 2 / 5 : scene_id. Échap efface le champ et masque les boutons. Ctrl+F depuis n'importe où dans le panneau remet le focus sur ce champ.
  • Graphe (zone principale) : nœuds déplaçables, zoomables à la molette, navigables en maintenant le clic molette ou en maintenant Espace + glisser. Une minimap en bas à droite donne une vue d'ensemble du graphe. Les positions des nœuds sont sauvegardées automatiquement et restaurées à chaque ouverture.
  • Panneau de détail (droite) : cliquer sur un nœud affiche son contenu complet. Les textes des messages et des choix sont éditables directement.

Nœuds du graphe

Chaque scène JSON correspond à un nœud. Le nom affiché dans le titre du nœud est l'id de la scène.

Indicateurs visuels

Indicateur Signification
avant l'ID Scène de départ (start_scene dans story.json)
après l'ID Scène avec free_input (saisie libre du joueur)
📝 après l'ID Scène avec des notes internes (_notes)
Couleur de titre Chaque contact a une couleur de barre de titre générée automatiquement depuis son ID — constante d'une session à l'autre
Texte en petit sous le titre Aperçu tronqué (60 car.) du premier message de la scène
⛔ Fin de parcours (rouge) La scène n'a aucune sortie — probable oubli d'auteur
⚠ Isolée (jaune) Aucune scène ne pointe vers cette scène — elle ne sera jamais atteinte

Types de connexions

Les flèches entre les nœuds sont colorées selon leur nature :

Couleur Type Description
Gris clair next ou choice Enchaînement normal ou choix du joueur
Orange trigger Déclenchement automatique via trigger_after_scene
Violet resume Reprise conditionnelle via resume_after_flag

Ports

Chaque nœud a : - Un port d'entrée (gauche) — reçoit les connexions des scènes précédentes - Un port de sortie par connexion (droite) — une par next, une par choix (choices[])

Si une scène a des choix sans destination (next absent), chaque choix dispose de son propre port de sortie — visible sans fil, prêt à être connecté. Glisser depuis ce port vers une autre scène écrit le next dans le bon choix.

Si une scène n'a ni choix ni next, un port → ? est affiché : il permet de tirer une connexion vers une autre scène, ce qui ajoutera un next de scène.


Panneau de détail

Story Editor — panneau de détail

L'éditeur est une aide pratique pour écrire des scènes sans toucher au JSON. Il couvre la grande majorité des cas d'usage courants. Certaines fonctionnalités avancées (conditions structurées and/or, médias, corrections différées, musique) restent accessibles uniquement via l'édition directe du fichier JSON — voir la section Ce que le JSON permet en plus en fin de document.

Cliquer sur un nœud ouvre le panneau de détail à droite. Tous les champs sont directement éditables et sauvegardés dès que le champ perd le focus (clic ailleurs ou Tab).

Niveau scène

Champ Interface
_notes Zone de texte — notes internes sur la scène, ignorées par le moteur. Apparaissent en vert en haut du panneau.
Contact Dropdown — tous les contacts du projet
trigger_after_scene Dropdown de scènes — se déclenche quand la scène choisie vient d'être jouée
resume_after_flag Dropdown de flags — attend en coulisse jusqu'à ce que ce flag soit activé
resume_after_delay Texte libre — accepte 300 (secondes), "5m", "1h"
free_input (var) Bouton + Saisie libre → champ texte pour le nom de variable
free_input_placeholder Champ texte — texte indicatif dans le champ de saisie du joueur

Par message

Champ Interface
Texte simple Zone de texte multi-ligne + × pour supprimer
Texte tableau (bulles) Chaque bulle éditable séparément + + bulle pour en ajouter
requires_flag Dropdown de flags — masque le message si le flag n'est pas actif
pause Dropdown — (aucune), short, medium, long
effects Ligne par effet : dropdown op + dropdown cible + champ valeur + × ; + Effet pour ajouter

Par choix

Champ Interface
Texte du bouton Zone de texte multi-ligne + × pour supprimer
message (bulle joueur) Absent : boutons + msg (une bulle) et + msgs [...] (plusieurs bulles successives) · Chaîne : champ texte éditable + × pour supprimer · Tableau : chaque bulle éditable séparément + + bulle pour en ajouter + × pour supprimer tout le tableau
flag Champ texte — flag activé à la sélection
requires_flag Dropdown de flags — masque ce choix si le flag n'est pas actif
next Dropdown de scènes — scène jouée après ce choix
effects Même interface que les effets de messages

Effets (effects)

Chaque effet se compose de trois champs :

Op Cible Valeur
set Dropdown de variables Valeur à affecter
add Dropdown de variables Valeur à ajouter
sub Dropdown de variables Valeur à soustraire
rename Dropdown de contacts Éditeur de nom inline : une ligne pour un nom invariant (identique dans toutes les langues), ou une ligne par code langue. Cliquez + Langue pour ajouter des entrées localisées — l'entrée invariante est automatiquement convertie en première entrée de langue. Un code langue apparaît en orange si aucun fichier *.{code}.json correspondant n'existe dans dialogues/.
set_status Dropdown de contacts online / away / offline / network_issue

Saisie libre vs Choix

free_input et choices sont mutuellement exclusifs : le moteur ignore les choix si une saisie libre est définie. L'éditeur le reflète : + Saisie libre est grisé si des choix existent, et + Choix est grisé si une saisie libre est active.


Édition depuis le graphe

Toutes les modifications sont écrites immédiatement dans le fichier JSON correspondant, puis le graphe est reconstruit automatiquement. Aucune confirmation n'est nécessaire sauf pour la suppression.

Créer une scène

Clic droit sur le fond du graphe (pas sur un nœud) → dialog de création :

  • ID : identifiant unique de la scène (ex. scene_10). Si l'ID existe déjà, la création est refusée.
  • Contact : liste déroulante de tous les contacts définis dans story.json.
  • Fichier : si plusieurs fichiers JSON existent dans dialogues/, un menu supplémentaire permet de choisir dans quel fichier écrire la scène.

La scène est ajoutée en fin de fichier avec un message vide { "text": "" }. Elle apparaît dans le graphe avec l'indicateur ⚠ Isolée jusqu'à ce qu'une connexion entrante soit créée.

Connecter deux scènes

Glisser depuis un port de sortie (cercle droit d'un nœud) vers le port d'entrée (cercle gauche) d'un autre nœud.

  • Si le port de sortie correspond à un choix, le champ next de ce choix est renseigné dans le JSON.
  • Si le port de sortie correspond au next de scène (ou au port → ?), le champ next de la scène est renseigné.
  • Si le port avait déjà une destination, elle est remplacée par la nouvelle.

On ne peut pas connecter un port trigger ou resume — ces connexions sont en lecture seule (elles reflètent des champs du JSON mais ne peuvent pas être modifiées depuis le graphe).

Déconnecter ou supprimer une connexion

Clic droit sur le nœud source → le menu contextuel liste toutes les connexions sortantes actives :

Supprimer cette scène
Dupliquer cette scène
─────────────────────
Déconnecter : C'est du spam → scene_02
Déconnecter : Oui, je vous reçois → scene_02

Cliquer sur une entrée "Déconnecter" supprime le next correspondant dans le JSON (le choix ou le next de scène reste, mais sans destination).

Dupliquer une scène

Clic droit sur le nœudDupliquer cette scène — ou Ctrl+D avec le nœud sélectionné.

La scène est copiée dans le même fichier JSON avec un nouvel ID ({id}_copy, puis {id}_copy2… en cas de collision). Les messages, les choix et tous les textes sont copiés ; les liens sortants (next, trigger_after_scene, resume_after_flag, resume_after_delay, choices[].next) sont effacés pour éviter les connexions dupliquées. L'opération est annulable avec Ctrl+Z.

Supprimer une scène

Clic droit sur le nœudSupprimer cette scène — ou Suppr avec le nœud sélectionné — → dialog de confirmation.

Sur confirmation : - La scène est retirée du fichier JSON qui la contient. - Tous les next et choices[].next qui pointaient vers cette scène sont supprimés dans tous les fichiers JSON du projet. - Le graphe est reconstruit.

La suppression peut être annulée avec Ctrl+Z.

Raccourcis clavier

Raccourci Condition Action
Ctrl+Z Annule la dernière modification
Ctrl+Y Rétablit la dernière modification annulée
Ctrl+F Focus sur le champ de recherche
F Aucun champ texte en focus Recentre et ajuste le zoom sur l'ensemble du graphe
Suppr Nœud sélectionné, aucun champ texte en focus Ouvre la confirmation de suppression
Ctrl+D Nœud sélectionné, aucun champ texte en focus Duplique la scène sélectionnée
← → Champ de recherche en focus, ≥ 2 résultats Résultat précédent / suivant
Échap Champ de recherche en focus Efface la recherche et relâche le focus

Les actions couvertes par l'annulation : connexion / déconnexion de scènes, création / suppression de scènes, édition de n'importe quel champ du panneau de détail, Reformater…, renommage de contact, toutes les modifications dans le panneau Contacts.

Exception : l'ajout et la suppression de langues (section Langues du panneau Paramètres) ne sont pas annulables — ces opérations peuvent créer plusieurs fichiers, modifier story.json et ui.csv, puis déclencher un réimport Godot.

L'historique d'annulation est limité à la session courante de l'éditeur.


Panneau Paramètres

Cliquer sur le bouton Paramètres dans la toolbar ouvre une fenêtre flottante pour les réglages globaux du projet. Chaque modification est écrite immédiatement, sans bouton Enregistrer. Les champs globaux et les vitesses de frappe sont sauvegardés respectivement dans story.json et theme.json.

Champs globaux

Champ Interface
title Texte libre — affiché dans les menus et la barre de titre de la fenêtre
menu_music Champ texte + bouton — ouvre l'explorateur de fichiers Godot filtré sur .ogg, .mp3, .wav. Chemin vers le fichier audio joué en boucle dans le menu principal. Laisser vide pour aucune musique.
start_scene Dropdown de scènes — première scène jouée au lancement d'une nouvelle partie
start_contact Dropdown de contacts — contact dont la conversation est affichée à l'écran au lancement ; si vide, le contact principal est utilisé

Vitesse de frappe

Configure les délais de saisie dans theme.json. Les modifications prennent effet au prochain lancement du jeu.

Champ Interface
Contacts SpinBox (0.01–0.50 s) — délai par caractère pour l'indicateur affiché pendant qu'un contact "écrit". Défaut : 0.08
Joueur SpinBox (0.01–0.50 s) — délai par caractère lors de la frappe des réponses du joueur. Défaut : 0.05

Langues

La section Langues liste les colonnes déclarées dans translations/ui.csv. L'affichage est mis à jour immédiatement, sans attendre la génération des fichiers .translation par Godot.

Élément Rôle
Chip par langue + × Chaque langue active est affichée avec un bouton ×. Celui-ci ouvre l'assistant de suppression décrit ci-dessous. Le bouton est grisé pour la dernière langue et pour la langue par défaut.
+ Ajouter une langue… Ouvre l'assistant de localisation complet décrit ci-dessous. Aucune écriture n'a lieu avant la confirmation finale.

Assistant d'ajout de langue

L'assistant se déroule en deux étapes :

  1. Configuration — saisir un code de langue (es, de, pt_BR…), choisir une langue source, puis décider s'il faut créer les dialogues localisés et préparer les champs localisés de story.json.
  2. Vérification — contrôler le nombre de textes d'interface, de champs de projet et la liste exacte des fichiers qui seront créés avant de cliquer sur Ajouter la langue.

À la confirmation, l'assistant :

  • ajoute une colonne à translations/ui.csv et la préremplit depuis la langue source choisie ;
  • crée, si demandé, un fichier nom.{langue}.json pour chaque dialogue disponible, en utilisant le fichier source localisé ou son fichier de fallback ;
  • prépare, si demandé, les names des contacts, les textes de history et les champs localisés de l'écran de fin dans story.json ;
  • demande à Godot de régénérer les ressources .translation ;
  • affiche un bilan et rappelle quels contenus copiés doivent maintenant être traduits.

Les fichiers localisés déjà présents ne sont jamais écrasés, même s'ils apparaissent entre l'aperçu et la confirmation. Les écritures sont transactionnelles et validées. En cas d'échec partiel, la langue n'est pas enregistrée dans ui.csv ; les fichiers déjà préparés sont conservés et l'assistant peut être relancé sans perte.

Si la création des dialogues est décochée, le moteur continue d'utiliser automatiquement les fichiers de la langue par défaut. L'assistant ne considère pas les textes copiés comme traduits : ils constituent uniquement une base de travail explicite.

La liste des langues proposée dans les paramètres du jeu est reconstruite automatiquement depuis ui.csv au prochain lancement.

Assistant de suppression de langue

Le bouton × d'une langue non protégée propose deux portées avant toute écriture :

  • Retirer uniquement du jeu supprime seulement sa colonne de translations/ui.csv. Les dialogues et les valeurs localisées de story.json restent intacts afin de pouvoir réactiver la langue plus tard.
  • Supprimer entièrement la langue supprime sa colonne de ui.csv, ses entrées dans les names, history et textes localisés de l'écran de fin, ainsi que tous les fichiers *.{langue}.json correspondants et la ressource .translation générée.

Une seconde étape affiche le nombre de valeurs localisées et la liste exacte des fichiers concernés. La confirmation finale est obligatoire pour appliquer la suppression.

Une suppression complète reste récupérable : chaque fichier retiré est renommé avec un suffixe .removed.{horodatage}, avec ses éventuels fichiers temporaires et sauvegardes. Il n'est donc plus détecté par le moteur, mais son contenu reste disponible localement. Ces archives sont exclues de Git. story.json utilise l'écriture transactionnelle habituelle et la colonne de ui.csv n'est supprimée qu'en dernier. En cas d'échec partiel, l'assistant peut être relancé.

La dernière langue ne peut jamais être supprimée. La langue par défaut est également protégée, car les fichiers JSON sans suffixe utilisent son contenu comme fallback. Pour la remplacer, il faut d'abord définir et préparer une autre langue par défaut.

Maintenance des fichiers de récupération

La section Maintenance des fichiers contient le bouton Nettoyer les fichiers de récupération…. Cet assistant permet de supprimer définitivement les anciennes récupérations lorsque le projet a été vérifié et fonctionne correctement.

Deux catégories peuvent être analysées séparément :

  • les sauvegardes rotatives .bak, .bak.2 et .bak.3 créées par les écritures sécurisées ;
  • les archives .removed.* conservées après la suppression complète d'une langue.

L'assistant parcourt uniquement les fichiers du projet et affiche leur chemin, leur taille et la liste exacte des éléments sélectionnés. Chaque fichier peut être décoché avant la confirmation finale. Une sauvegarde .bak dont le fichier principal est absent ou invalide est automatiquement protégée, car elle peut constituer la dernière copie récupérable.

Le nettoyage est définitif et ne crée pas une nouvelle sauvegarde des fichiers supprimés. Les fichiers .tmp, les quarantaines .corrupt.*, .git, .godot, les dossiers d'export et les sauvegardes de parties situées dans user:// sont volontairement exclus.

Écran de fin

La section Écran de fin configure ce qui s'affiche après une scène marquée "end": true.

Champ Interface
title Un champ par langue active — titre principal affiché en grand. Sauvegardé comme dict localisé si plusieurs langues, comme string si une seule.
text Un champ par langue active — texte secondaire sous le titre (accroche, annonce de suite…). Même format que title.
lien URL Texte libre — URL ouverte au clic (ex : page itch.io). Vide = aucun lien
lien texte Texte libre — libellé affiché sur le lien. Vide = l'URL brute s'affiche
glitch Case à cocher — active le scramble de texte sur le titre + scanlines animées + flicker
show_stats Case à cocher — affiche le nombre de messages échangés pendant la session

Pour marquer la scène finale, ajoutez "end": true directement dans le JSON de la scène (voir le guide auteur).


Panneau Contacts

Cliquer sur le bouton Contacts dans la toolbar ouvre une fenêtre flottante pour gérer la liste des personnages dans story.json. Chaque modification est écrite immédiatement, sans bouton Enregistrer.

Liste des contacts

Chaque contact est affiché sous forme de carte avec tous ses champs éditables :

Champ Interface
id Texte libre — si modifié, toutes les références contact_id dans les fichiers de dialogue sont mises à jour automatiquement
name Texte libre — nom affiché dans la liste de contacts et la barre de titre
is_main Case à cocher — désigne le contact qui reçoit toutes les scènes sans contact_id explicite ; cocher un contact décoche automatiquement tous les autres
avatar Champ texte + bouton — cliquer sur ouvre l'explorateur de fichiers Godot directement dans assets/avatars/. Le chemin peut aussi être saisi manuellement (ex : res://assets/avatars/maeve.png). Vide = initiale du nom sur fond coloré. Les formats acceptés sont PNG, JPG, JPEG et WEBP.
status Dropdown — online, away, offline, network_issue
pending_scene Dropdown de scènes — scène mise en attente pour ce contact au démarrage ; le joueur voit un choix en suspens dès l'ouverture de la conversation
names Section « Noms localisés » — liste de paires code langue / nom. Bouton + Langue pour ajouter une entrée (un placeholder ?? apparaît en orange — le remplacer par le code réel). Le code langue est coloré en orange si aucun fichier de dialogue correspondant (*.{code}.json) n'est trouvé dans dialogues/. Voir la section names du guide auteur.
history Liste de lignes — chaque entrée a une case (envoyé par le joueur), un champ date YYYY-MM-DD (optionnel), un champ heure HH:MM, un bouton 📅 pour ouvrir le sélecteur visuel, et un champ texte par langue active. Si le projet a plusieurs langues (ex : fr et en), chaque ligne affiche autant de champs que de langues — préfixés par leur code. Si la date est vide, le message s'affiche comme un message du jour ; si elle est antérieure à aujourd'hui, l'horodatage affiché est JJ-MM-AAAA HH:MM (locale FR) ou AAAA-MM-JJ HH:MM (autres locales).
  • + Contact — ajoute une nouvelle carte contact
  • × sur une carte — demande une confirmation avant de supprimer le contact de story.json
  • + msg sur une carte — ajoute une entrée d'historique
  • × sur une ligne d'historique — supprime l'entrée immédiatement

Renommer un id est sans risque : le panneau scanne tous les fichiers de dialogue du projet et met à jour chaque contact_id qui correspondait à l'ancienne valeur. Le champ start_contact global est aussi mis à jour si nécessaire.


Panneau Flags

Cliquer sur le bouton 🚩 Flags dans la toolbar ouvre une fenêtre flottante en lecture seule listant tous les flags utilisés dans le projet, dérivés en temps réel depuis les scènes chargées.

Pour chaque flag, trois catégories sont affichées (uniquement celles non vides) :

Catégorie Source dans le JSON
✏️ Défini par choices[].flag — scènes dont un choix active ce flag
⏱ Attendu par resume_after_flag — scènes qui attendent ce flag pour se déclencher
? Requis par requires_flag, condition (à tous les niveaux : scène, message, choix) — scènes qui consultent ce flag

Cliquer sur un ID de scène dans la liste centre le graphe sur ce nœud et ouvre son panneau de détail.

Le panneau se met à jour automatiquement après chaque Refresh du graphe.


Panneau Analyser

Cliquer sur le bouton 📊 Analyser dans la toolbar ouvre une fenêtre flottante en lecture seule présentant une analyse du récit calculée en temps réel depuis les scènes chargées.

Section Contenu
Vue d'ensemble Nombre de scènes, messages, choix, fins (sans continuation), scènes inaccessibles, boucles et flags inutilisés (avec indicateur coloré si > 0)
Accessibilité Pourcentage de scènes accessibles depuis start_scene (parcours exhaustif depuis la scène de départ) ; liste cliquable des scènes inaccessibles
Flags inutilisés Flags activés par choices[].flag mais jamais vérifiés dans requires_flag, condition ou resume_after_flag (section absente si tous les flags sont utilisés)
Boucles Circuits fermés détectés par exploration des chemins — scènes où le joueur peut rester indéfiniment sans condition de sortie (section absente si aucune boucle)
Personnages Nombre de messages par contact, trié par volume décroissant, avec pourcentage du total
Durée indicative ≈ Xh YY ou ≈ N min — basé sur 200 mots/min en comptant toutes les branches (chemin complet inclus)

Cliquer sur un ID de scène dans les sections Accessibilité ou Boucles centre le graphe sur ce nœud.

Le panneau se recalcule automatiquement à chaque ouverture (si déjà ouvert, cliquer à nouveau le bouton rafraîchit les données).


Ce que le JSON permet en plus

L'éditeur couvre la grande majorité des scénarios. Les fonctionnalités suivantes nécessitent encore une édition directe du fichier JSON :

Fonctionnalité Pourquoi JSON uniquement
condition structurée (and/or/flag/var) Logique booléenne complexe, requires_flag couvre la majorité des cas
media (image dans une bulle) Affiché en lecture seule dans l'éditeur (📷 nom du fichier)
edit (corrections différées) Le texte corrigé (corrected_text) est éditable ; le type et le délai restent en lecture seule
time (délai d'apparition d'un message) Cas avancé rare
music Cas avancé rare

Après une édition manuelle, le bouton Reformater… permet de remettre les fichiers voulus dans le format canonique décrit ci-dessous.


Format JSON produit par l'éditeur

L'éditeur écrit le JSON en respectant l'ordre sémantique des clés à trois niveaux :

Scène :

_notes → id → contact_id → trigger_after_scene → resume_after_flag → resume_after_delay → messages_in → free_input → free_input_placeholder → music → next → choices

Message :

text → edit → effects → media → pause → requires_flag → condition

Choix :

text → message → flag → requires_flag → condition → next → effects

Les messages, choix et tableaux de texte sont entièrement développés : chaque objet et chaque texte possède sa propre ligne. L'indentation utilise des tabulations.

Reformater des fichiers JSON

Le bouton Reformater… n'écrit rien immédiatement. Il ouvre d'abord une fenêtre compacte qui liste, par ordre alphabétique, tous les fichiers .json présents dans dialogues/.

  1. La langue actuellement éditée est indiquée en haut de la fenêtre.
  2. Les fichiers réellement utilisés pour cette langue sont présélectionnés.
  3. Lorsqu'un fichier localisé n'existe pas, le fichier de la langue par défaut utilisé à sa place est signalé comme Fallback et mis en évidence. Le reformatage ne crée pas de variante localisée manquante.
  4. Langue active rétablit cette présélection ; Tous les fichiers sélectionne toute la liste. Chaque fichier peut aussi être coché ou décoché individuellement.
  5. Le bouton de confirmation indique le nombre de fichiers concernés et reste désactivé tant que la sélection est vide.

Seuls les fichiers cochés au moment de la confirmation sont écrits. Le reformatage modifie uniquement la présentation du document — indentation, retours à la ligne et ordre canonique des clés — sans modifier les valeurs ni la logique narrative. Chaque écriture utilise le mécanisme sécurisé du moteur et conserve une copie de récupération. L'opération peut également être annulée avec Ctrl+Z dans le Story Editor.

Avec un grand nombre de langues ou de fichiers, seule la liste défile verticalement : les actions de sélection, de confirmation et d'annulation restent visibles. Le chemin complet et le détail d'un fallback sont disponibles dans l'infobulle de chaque fichier.


Localisation

Le plugin lit les fichiers de dialogue en appliquant la même logique de locale que le jeu : - Il préfère acte1.fr.json si la langue système est fr, sinon acte1.json - La langue lue correspond au réglage de la langue système de l'OS, pas au réglage dans le jeu

Prévisualiser une autre langue : le dropdown de locale dans la toolbar ([fr v] dans l'ASCII ci-dessus) permet de forcer la locale du plugin indépendamment de la langue système. Sélectionner en charge acte1.en.json à la place de acte1.json — pratique pour vérifier la version anglaise depuis un OS configuré en français. Le choix est perdu au redémarrage de Godot.


Architecture

Cette section s'adresse aux développeurs qui souhaitent modifier ou étendre le plugin. Elle n'est pas nécessaire pour écrire du contenu narratif.

Le plugin est dans addons/story_editor/ et ne touche à aucun fichier existant du projet hors des actions d'édition explicites.

Fichier Rôle
plugin.cfg Manifest Godot (nom, version)
plugin.gd EditorPlugin — ajoute/retire le panneau
StoryEditorPanel.tscn Scène du panneau (HSplitContainer[GraphEdit, ScrollContainer]) + toolbar
StoryEditorPanel.gd Logique principale : parsing, layout BFS, rendu, édition, écriture JSON ; ouvre les fenêtres Contacts et Paramètres ; possède l'undo/redo
SceneDetailPanel.gd RefCounted — formulaire d'édition de scène (panneau droit) ; toutes les fonctions _populate_* et _add_* ; reçoit ses dépendances via des callables injectés par StoryEditorPanel
StoryPanelBase.gd Classe de base partagée par ContactsPanel et StorySettingsPanel : lecture/écriture de story.json, callables undo/redo, helpers UI (_section, _line_edit, _dropdown, etc.)
ContactsPanel.gd Panneau Contacts — liste des personnages uniquement ; étend StoryPanelBase
StorySettingsPanel.gd Panneau Paramètres — réglages globaux, langues, écran de fin ; étend StoryPanelBase
scene_parser.gd RefCounted autonome — lit story.json + dialogues/*.json avec support locale
FlagsPanel.gd Panneau Flags — liste en lecture seule tous les flags du projet avec leurs scènes d'origine ; Control pur, non connecté à StoryPanelBase
AnalysisPanel.gd Panneau Analyser — analyse en lecture seule : accessibilité par parcours depuis start_scene, détection de cycles, flags inutilisés, compte par contact, durée indicative ; Control pur
json_utils.gd Helpers JSON statiques : expand() / compact() (sérialiseur sur mesure), ordered_scene/message/choice() (ordre stable des clés pour des diffs lisibles)

scene_parser.gd est volontairement découplé de dialogue_loader.gd pour fonctionner dans le contexte éditeur (les autoloads du jeu ne sont pas disponibles dans un plugin @tool).

ContactsPanel.gd et StorySettingsPanel.gd étendent tous deux StoryPanelBase.gd et reçoivent quatre callables injectés par StoryEditorPanel : get_scene_ids, begin_mutation, end_mutation, snapshot_file. Les deux panneaux communiquent avec le panneau principal via les signaux story_modified et error_occurred. ContactsPanel émet en plus rename_contact_requested, dont les écritures dans les fichiers de dialogue sont déléguées à StoryEditorPanel (qui possède _write_json).

Les scènes sont écrites via _write_json() qui appelle JsonUtils.ordered_scene() (tri sémantique des clés, défini dans json_utils.gd) puis JsonUtils.expand() (sérialiseur sur mesure : expansion jusqu'à la profondeur 3, compact au-delà). story.json utilise le même sérialiseur dans ContactsPanel.