Fonctions Lua (1ère partie)

Bienvenue dans ce premier article consacré aux fonctions EEP et Lua. Nous allons commencer en douceur l'apprentissage pour l'écriture de scripts avec des exemples concrets pour progresser au travers d'un parcours ludique et enrichissant.

Cet article reprend le classement par thèmes des fonctions du manuel Lua officiel EEP mais va plus loin que la simple théorie en illustrant chaque fonction par un ou plusieurs exemples créés pour l'occasion ou issus de projets réels.

Pour les débutants, si vous n'avez pas ou peu de connaissances en programmation, nous vous conseillons de lire l'article sur Les bases du langage Lua, il vous apportera des informations utiles pour commencer l'apprentissage du langage Lua.

Les bases

EEP contient une multitude de fonctions Lua créées spécialement pour lui. Elles sont faciles à reconnaitre car elles commencent toutes par le même préfixe EEP suivi du nom de la fonction. Quelques exemples :

  • EEPSetTime()
  • EEPGetSignalTrainName()
  • EEPSetTrainSpeed()
  • EEPTrainLooseCoupling()
  • EEPShowInfoStructure()
  • ...

S'il y avait qu'une seule fonction à retenir, ce serait EEPMain(). Rappelez-vous dans l'éditeur Lua, il s'agit de la fonction principale ajoutée automatiquement lors de la création d'un nouveau projet.

Vous remarquerez à l'étude des fonctions EEP qu'elles contiennent pour la plupart souvent les syllabes Get et Set. Exemple :

  • EEPSetTime()
  • EEPGetSignalTrainName()
  • EEPSetTrainSpeed()
  • EEPGetAnlLng()
  • EEPSetCameraRotation()

Nous pouvons traduire l'action Get par Obtenir ou récupérer une valeur et l'action Set par modifier ou assigner une valeur. Retenez bien ces deux notions importantes car nous allons souvent les utiliser.

Sinon en dehors des fonctions Lua spécialement créées pour EEP, nous avons deux autres types de fonctions :

  • Les fonctions propres au langage Lua (manipulation des chaines de caractères, des calculs, des boucles, des tables....)
  • Les fonctions personnalisées ou utilisateur (celles que vous allez nommer et créer pour effectuer un travail quelconque, un calcul, etc...).

Naturellement, nous allons manipuler des variables. Avec Lua le type des variables est assez limité comparé à d'autres langages plus typés. Les variables les plus utilisées avec EEP sont numérique, alphanumérique, nulle, booléen, table.

Rappel : Une variable peut contenir une valeur nulle ce qui revient à dire que le contenu de cette variable est totalement vide. La variable existe bien mais elle est vide, c'est à dire qu'elle ne contient aucune chaine de caractères ou pas même la valeur numérique 0. Elle est vide, point à la ligne. Vous pouvez la comparer à une coquille vide. Vous comprendrez plus loin dans cet article et les suivants pourquoi ce type de variable particulier est parfois bien utile. Une variable avec la valeur nulle est déclarée avec le mot-clé nil.

Quoiqu'il en soit, une variable doit toujours être déclarée. C'est une bonne habitude à prendre dès le départ. Même si Lua n'impose pas la déclaration explicite des variables. Des variables bien nommées et déclarées évitent des éventuelles erreurs d'exécution et font gagner un temps précieux lorsqu'il faut fouiller dans le code et cela est d'autant plus vrai quand le code est volumineux.

Si vous voulez en savoir plus sur les mots clé du langage Lua, voici l'adresse d'un excellent site pour découvrir ou approfondir vos connaissances avec ce langage.

Variables et fonctions Lua pour EEP17.1

Nous allons étudier en plusieurs articles la liste de toutes les variables et fonctions Lua pour EEP disponibles jusqu'à la version EEP17.1 plugin 1. Elles sont classées par thèmes. Chaque fonction est détaillée et accompagnée d'un ou plusieurs exercices sous forme d'un petit projet. Tous les projets sont téléchargeables et vous pouvez les reproduire, les utiliser et les partager sans restriction.

Variables système

EEP fournit ses propres variables système utilisables n'importe où dans un script. Elles sont au nombre de six.

EEPVer

A partir de

Objectif

EEP 10.2 Plug-in 2.

Retourne la version actuelle de votre programme EEP.

EEPVer

Projet de démonstration avec la fonction EEPVer.

Exemple :

Ouvrez la fenêtre de l'éditeur lua et entrez le code suivant :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
clearlog()

function EEPMain()
  return 1
end

print("Le numéro de votre version EEP est le : ", EEPVer)

Ci-dessous le résultat dans la fenêtre de l'éditeur :

Image 1 - Code Lua EEPVer dans EEP

Une fois votre texte collé dans l'éditeur, n'oubliez pas de cliquer comme d'habitude sur le bouton Recharger le script pour valider le script et fermer la fenêtre. Ensuite affichez la fenêtre d'évènement si celle-ci n'est pas déjà activée.

Maintenant passez en mode 3D pour vérifier si le script fonctionne :

Image 2 - Code Lua EEPVer dans EEP

Impeccable ! notre script affiche bien la phrase entre les guillemets et le numéro actuel de la version EEP en cours d'exécution. Nous aborderons la syntaxe de la fonction print dans le chapitre qui lui sera dédié.

EEPTime

A partir de

Objectif

EEP 10.2 Plug-in 2.

Retourne l'heure actuelle EEP. La valeur correspond au nombre de secondes écoulées depuis minuit. Ici nous parlons bien de l'heure EEP et non pas de l'heure système de l'ordinateur.

EEPTime

Projet de démonstration avec la fonction EEPTime.

Exemple :

Ouvrez la fenêtre de l'éditeur Lua et entrez le code suivant :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
clearlog()

function EEPMain()
  return 1
end

print(EEPTime, " secondes se sont écoulées depuis minuit.")

Ci-dessous le résultat dans la fenêtre de l'éditeur :

Image 1 - Code Lua EEPTime dans EEP

Une fois votre texte collé dans l'éditeur, n'oubliez pas de cliquer comme d'habitude sur le bouton Recharger le script pour le valider et fermer la fenêtre. Ensuite affichez la fenêtre d'évènement si celle-ci n'est pas déjà activée.

Maintenant passez en mode 3D pour vérifier si le script fonctionne :

Exécution correcte du code Lua EEPTime dans EEP

Ici aussi notre script affiche bien le nombre de secondes écoulées depuis minuit.

EEPTimeH

A partir de

Fonction

EEP 10.2 Plug-in 2.

Retourne l'heure EEP actuelle sans les minutes ni les secondes.

EEPTimeH

Projet de démonstration avec la fonction EEPTimeH.

Exemple :

Ouvrez la fenêtre de l'éditeur lua et entrez le code suivant :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
clearlog()

function EEPMain()
  return 1
end

print("Il est actuellement : ", EEPTimeH, " H à l'heure EEP")

Une fois votre texte collé dans l'éditeur, n'oubliez pas de cliquer sur le bouton Recharger le script pour valider le script et fermer la fenêtre.

Maintenant passez en mode 3D pour vérifier si le script fonctionne :

Exécution correcte du code Lua EEPTimeH dans EEP

Notre script affiche bien la partie "Heure" de l'heure EEP.

EEPTimeM

A partir de

Fonction

EEP 10.2 Plug-in 2.

Retourne la partie des minutes de l'heure EEP actuelle.

EEPTimeM

Projet de démonstration avec la fonction EEPTimeM.

Exemple :

Ouvrez la fenêtre de l'éditeur lua et entrez le code suivant :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
clearlog()

function EEPMain()
  return 1
end

print(EEPTimeH, " minutes se sont écoulées depuis le début de l'heure EEP actuelle")

Une fois votre texte collé dans l'éditeur, cliquez sur le bouton Recharger le script pour valider le script et fermer la fenêtre.

Maintenant passez en mode 3D pour vérifier si le script fonctionne :

Exécution correcte du code Lua EEPTimeM dans EEP

Notre script affiche bien la partie "Minute" de l'heure EEP.

EEPTimeS

A partir de

Fonction

EEP 10.2 Plug-in 2.

Retourne la partie des secondes de la minute EEP actuelle.

EEPTimeS

Projet de démonstration avec la fonction EEPTimeS.

Exemple :

Ouvrez la fenêtre de l'éditeur lua et entrez le code suivant :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
clearlog()

function EEPMain()
  return 1
end

print(EEPTimeS, " secondes se sont écoulées depuis le début de la minute EEP en cours")

Une fois votre texte collé dans l'éditeur, cliquez sur le bouton Recharger le script pour valider le script et fermer la fenêtre. Maintenant passez en mode 3D pour vérifier si le script fonctionne :

Exécution correcte du code Lua EEPTimeS dans EEP

Notre script affiche bien la partie "Seconde" de la minute EEP.

EEPLng

A partir de

Objectif

EEP 17.

Retourne l’abréviation correspondante à la langue de la version EEP installée.
GER = version allemande
ENG = version anglaise
FRA = version française

Cette fonction peut être utilisée si vous construisez un projet avec des fonctions d'affichage dans l'éventualité de le partager avec des utilisateurs d'autres pays.

EEPLng

Projet de démonstration avec la fonction EEPLng

Exemple n° 1 :

Ouvrez la fenêtre de l'éditeur lua et entrez le code suivant :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
clearlog()

function EEPMain()
  return 1
end

if EEPLng == "GER" then
    print("Dies ist eine deutsche EEP-Version")
  elseif EEPLng == "ENG" then
    print("This is an English version of EEP")
  elseif EEPLng == "FRA" then
    print("Vous avez la version française d'EEP")
end

Pour le moment, ne vous occupez pas des instructions if - elseif- end, nous les aborderons plus tard.

Une fois votre texte collé dans l'éditeur, cliquez sur le bouton Recharger le script pour valider le script. Maintenant passez en mode 3D pour vérifier si le script fonctionne :

Image 1 - Code Lua EEPLng dans EEP

Notre script indique qu'EEP est bien en version française. Pour le vérifier, nous pouvons tester la valeur de la variable EEPLng comme dans l'exemple ci-dessous.

Exemple n° 2 :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
clearlog()

function EEPMain()
  return 1
end

if EEPLng == "GER" then
    print("Dies ist eine deutsche EEP-Version")
  elseif EEPLng == "ENG" then
    print("This is an English version of EEP")
  elseif EEPLng == "FRA" then
    print("Vous avez la version française d'EEP")
end

print("La valeur de la variable EEPLng est bien : ", EEPLng)

Vérifions ceci dans la fenêtre d'évènements :

Image 2 - Code Lua EEPLng dans EEP

Nous sommes bien en version française car la variable EEPLng est égale à FRA.

Synthèse

Nous venons de voir les variables système EEP et nous avons appris à commenter le code sur une ou plusieurs lignes. Dans le chapitre suivant, nous allons aborder les fonctions système et rentrer dans le détail en utilisant les variables avec des exemples simples.

Fonctions système
clearlog()

Paramètres

Valeur(s) retournée(s)

A partir de

Objectif

Aucun

Aucune

EEP 10.2 Plug-in 2.

Efface le contenu de la fenêtre d’événements

Exemple :

Ouvrez la fenêtre de l'éditeur lua et entrez le code suivant :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
clearlog()

function EEPMain()
  return 1
end

Une fois votre texte collé dans l'éditeur, cliquez sur le bouton Recharger le script. Maintenant passez en mode 3D pour constater l'effacement de l'ancien contenu dans la fenêtre d'évènements.

print()

Syntaxe

Paramètres

Valeur(s) retournée(s)

A partir de

Objectif

print("Texte1", "Texte2", … , variable)

Plusieurs

Aucune

EEP 10.2 Plug-in 2.

Affiche dans la fenêtre d'évènements le texte qui se trouve entre guillemets.

print

Projet de démonstration avec le mot-clé print

Reprenons nos exemples. A la ligne n° 1, nous avons la forme la plus simple de l'instruction print : une phrase accompagnée d'une variable. A la ligne n° 3, la variable est au début et la phrase à la suite. A la ligne n° 5, la variable se trouve au milieu de deux phrases :

print("Votre version EEP est le numéro : ", EEPVer)

print(EEPTime, " secondes se sont écoulées depuis minuit.")

print("Il est actuellement : ", EEPTimeH, " H à l'heure EEP")

Pour résumer, une fonction print peut contenir une ou plusieurs phrases et une ou plusieurs variables. Il est important de retenir ceci :

  1. La fonction print doit impérativement être écrite en minuscule. Print ou PRINT engendrera un message d'erreur et stoppera l'exécution du script,
  2. Chaque phrase ou chaque variable à l'intérieur des parenthèses de l'instruction print doit être séparée par une virgule,
  3. Le texte d'une phrase doit être entouré avec des guillemets : "je suis une phrase entourée de guillemets",
  4. Une variable numérique ne doit jamais être entourée de guillemets sinon son nom sera affiché en tant que phrase
EEPMain()

Syntaxe

Paramètres

Valeur(s) retournée(s)

A partir de

Fonction

EEPMain()

Aucun

Aucune

EEP 10.2 Plug-in 2.

Est exécutée par cycles de 200 millisecondes 5 fois par seconde. Convient à toute action devant être exécutée régulièrement.

Remarque

  • Doit être déclaré dans le script, sinon EEP ne se connectera pas à Lua.
  • EEP exécute cette fonction sans aucun paramètre.
  • La fonction doit renvoyer un nombre différent de 0 pour être appelée à nouveau.
  • Le renvoi de la valeur 0 désactive l'appel répété de cette fonction. Toutes les autres fonctions de votre script restent actives.
  • Si cette fonction renvoie autre chose qu'un nombre, EEP cessera d'utiliser le script.

EEPMain

Projet de démonstration avec la fonction EEPMain

Exemple :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
-- S'exécute 5 fois par seconde
function EEPMain()
    return 1
end

-- Désactive la fonction, ne s'exécute plus 5 fois par seconde mais laisse continuer les autres fonctions s'exécuter tant que le script est en action
function EEPMain()
    return 0
end

Comme son nom l'indique, la fonction EEPMain() est LA fonction Lua incontournable dans EEP. Vous êtes dispensé de l'écrire car elle est créée automatiquement à chaque nouveau projet. Le principe pour lequel cette fonction est appelée 5 fois par seconde est tentant et intéressant pour exécuter des actions récurrentes mais gardez bien à l'esprit qu'une charge de travail supplémentaire est demandée à EEP et avec des longs scripts contenant d'innombrables fonctions, il convient sans aucun doute d'analyser différemment la conception dès le départ pour ne pas se retrouver bloqué devant un projet qui s'exécute lentement voire planter complètement la machine (situation déjà constatée avec un script mal écrit...).

EEPPause()

Syntaxe

Paramètres

Valeur(s) retournée(s)

A partir de

Objectif

EEPPause(statut)

Un

Une

EEP 14.1 Plug-in 1.

Active et désactive la fonction pause dans EEP.

Remarque

  • Statut = 0 : Désactive le mode pause
  • Statut = 1 : Active le mode pause
  • Statut = 2 : Stoppe les opérations dans EEP et LUA. Ensuite, le fonctionnement ne peut être repris qu'en appuyant sur la touche P
  • La valeur renvoyée est égale à 0 si le mode pause est désactivée ou égale à 1 si le mode est actif.

EEPPause

Projet de démonstration avec la fonction EEPPause

Exemple :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
function EEPMain()
    return 1
end

g_nbr_Resultat = nil

CONST_STATUT_DESACTIVE = 0
CONST_STATUT_ACTIF = 1
CONST_STATUT_STOP = 2

-- Si eep est en pause, la fonction EEPPause avec l'argument CONST_STATUT_DESACTIVE va redémarrer EEP
g_nbr_Resultat = EEPPause(CONST_STATUT_DESACTIVE)

-- Si eep n'est pas en pause, la fonction EEPPause avec l'argument CONST_STATUT_ACTIF va mettre EEP en pause
g_nbr_Resultat = EEPPause(CONST_STATUT_ACTIF)

-- Si eep n'est pas en pause, la fonction EEPPause avec l'argument CONST_STATUT_STOP va mettre EEP en pause et il ne pourra être réactivé qu'en appuyant sur la touche P du clavier.
g_nbr_Resultat = EEPPause(CONST_STATUT_STOP)

Avant de passer en mode 3D pour exécuter le script, arrêtons-nous quelques instants pour analyser le code ci-dessus. Nous trouvons à la ligne n° 5 une variable numérique globale et nous lui avons assigné la valeur nil. Pourquoi cette erreur ? Rassurez-vous, il ne s'agit aucunement d'une erreur mais le mot nil est un mot réservé du langage Lua qui veut dire Nul. Rappelez-vous, nous en avons déjà parlé au début de l'article :

Rappel : Une variable peut contenir une valeur nulle ce qui revient à dire que le contenu de cette variable est totalement vide. La variable existe bien mais elle est vide, c'est à dire qu'elle ne contient pas de chaine de caractères vide ou pas même la valeur numérique 0. Elle est vide, point à la ligne.

Concrètement le fait d'avoir assigné la valeur nil (nul) à notre variable veut dire qu'elle existe et qu'elle s'attend à recevoir dans le futur un type de donnée quelconque. Ici en l'occurrence il s'agit d'une valeur numérique. On aurait pu écrire g_nbr_Resultat = 0 mais dans ce cas précis, cela revient à affecter directement la valeur du statut de la fonction égal à 0 (Désactiver le mode pause) et ce n'est peut-être pas ce qu'on désire faire dans un premier temps.

Conseil : si vous ne connaissez pas la valeur de départ pour une variable, affectez-lui toujours la valeur nil.

Et pour terminer, trois constantes ont été créées pour l'occasion aux lignes 7 à 9 et sont utilisées comme arguments entre parenthèses conformément à la syntaxe de la fonction. Lorsque la fonction est exécutée, la valeur renvoyée dans la variable g_nbr_Resultat nous informe si EEP est en pause ou non.

Une fois votre texte collé dans l'éditeur, cliquez sur le bouton Recharger le script. Maintenant passez en mode 3D pour exécuter le script. Vous devriez avoir un message au milieu de l'écran indiquant qu'EEP est en mode pause :

Exécution correcte du code Lua EEPPause() dans EEP
EEP en mode pause

L'apparition de ce message signifie que notre script a bien été exécuté car la ligne n° 18 du script est la dernière a être prise en compte et nous avons paramétré g_nbr_Resultat = EEPPause(CONST_STATUT_STOP). Ce statut stoppe les opérations dans EEP et Lua. Si nous avions écrit g_nbr_Resultat = EEPPause(CONST_STATUT_DESACTIVE), le mode pause serait désactivé et donc EEP serait de nouveau actif.

EEPSetTime()

Syntaxe

Paramètres

Valeur(s) retournée(s)

A partir de

Objectif

EEPSetTime(Heure, Minute, Seconde)

Trois

Une

EEP 15.

Modifie l'heure EEP selon votre choix.

Remarque

  • Le premier argument indique l'heure
  • Le deuxième argument indique les minutes
  • Le troisième argument indique les secondes.
  • Les trois arguments sont obligatoires.
  • La valeur renvoyée est égale à true (vrai) si l'exécution de la fonction s'est déroulée correctement sinon elle retourne false (faux).

EEPSetTime

Projet de démonstration avec la fonction EEPSetTime

Exemple :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
function EEPMain()
    return 1
end

g_boolResultat = nil

-- Configurer la nouvelle heure EEP
g_boolResultat = EEPSetTime(18, 35, 20)

-- Afficher le résultat de la fonction
print("Résultat de la fonction : ", g_boolResultat)

Une fois votre texte collé dans l'éditeur, cliquez sur le bouton Recharger le script. Maintenant passez en mode 3D pour exécuter le script et regardons le résultat via la fonction print :

Exécution correcte du code Lua EEPSetTime() dans EEP

Dans cet exemple, le type de la variable g_boolResultat est un booléen. Quelle est sa signification ? Un booléen ne peut contenir que deux résultats : vrai ou faux traduit par true ou false en anglais. True = vrai, et false = faux. Le résultat de la fonction nous renvoie la valeur true afin de nous informer que l'exécution de la fonction s'est déroulée avec succès et donc le changement d'heure EEP a bien été effectué.

Ici aussi ne sachant pas à l'avance quel sera le résultat, la valeur nil a été affectée lorsque la variable a été déclarée.

Focus sur la construction des fonctions

Avant de continuer, il est important de comprendre comment sont utilisées les fonctions. Aussi bien celles du langage Lua, EEP et les vôtres. Vous vous posez certainement des questions : Pourquoi utiliser des fonctions ? quand faut-il les employer et à quel moment ? c'est quoi les arguments entre parenthèses ? est-ce que les arguments sont obligatoires ? Une fonction peut-elle renvoyer une valeur ? etc...

Voici quelques éléments de réponses pour vous aider à y voir plus clair.

Pourquoi utiliser une fonction ?

Sans fonction, l'exécution du code d'un programme serait linéaire du début jusqu'à la fin. Arrivé à la fin, le programme se terminerait sans possibilité de revenir en arrière. Dans ce cas, comment prendre la main et le contrôle sur le programme ? Prenons un exemple très simple : vous voulez effectuer un calcul plusieurs fois durant toute la durée d'exécution d'un projet. L'opération ne change pas, seules changent les valeurs à calculer. Il est évident qu'il serait tout à fait inconcevable d'écrire de façon linéaire plusieurs fois le même calcul pour des raisons évidentes :

  1. On ne connait pas à l'avance les valeurs à calculer,
  2. On ne connait pas à quel moment exact il faudra calculer ces valeurs,
  3. L'évènement déclencheur pour la demande du calcul peut être un contact, un signal ou même l'appel d'une autre fonction, etc...

Pour toutes ces raisons, faire appel aux fonctions permet de structurer le programme et de le "compartimenter" afin d'exécuter à la demande telle ou telle partie du code seulement lorsque c'est nécessaire.

Ci-dessous, deux exemples simples pour bien comprendre la différence avec un programme sans et un programme écrit avec des fonctions :

1er exemple de code linéaire sans fonction
-- Début du programme
-- Calcul d'un temps de trajet entre un point A et un point B et
-- affichage de la durée en secondes lorsque le train s'arrête en gare

function EEPMain()
  return 1
end

-- On déclare les variables
g_Debut_A = nil
g_Fin_B = nil
g_Difference = nil

-- Opération pour calculer la durée en secondes d'un trajet entre A et B
g_Debut_A = EEPTimeS
g_Fin_B = EEPTimeS
-- Soustraction entre le temps du point B et du point A
g_Difference = g_Fin_B - g_Debut_A

-- On commute le signal n° 1 lorsque le train passe au point B
EEPSetSignal(1)
-- On affiche le résultat
print("Le nombre de secondes écoulées entre le Point A et B est de : ", g_Difference, " secondes")

-- Le programme se termine

Dans ce premier exemple, le code entier va être exécuté en un seul bloc (dès le mode 3D activé) et se terminera directement à la ligne n° 25. Naturellement la différence en seconde entre g_Debut_A et g_Fin_B (lignes 15 et 16) sera égale à 0 car vu la rapidité d'exécution, les deux lignes seront traitées à quelques millièmes de secondes d'intervalle.

Ci-dessous un autre exemple du même code mais en utilisant trois fonctions :

2ème exemple de code avec trois fonctions
-- Début du programme
-- Calcul d'un temps de trajet entre un point A et un point B et
-- affichage de la durée en secondes lorsque le train s'arrête en gare

function EEPMain()
  return 1
end

-- On déclare les variables
g_Debut_A = nil
g_Fin_B = nil
g_Difference = nil

-- Fonction appelée par un premier contact
function fnc_Debut()

	-- Prise en compte du temps au point A
	g_Debut_A = EEPTimeS
	
end

-- Fonction appelée par un second contact
function fnc_Fin()

	-- Prise en compte du temps au point B
	g_Fin_B = EEPTimeS
	-- Soustraction entre le temps du point B et du point A
	g_Difference = g_Fin_B - g_Debut_A
	
end

-- Fonction appelée par un troisième contact lorsque le train entre en gare
function fnc_Arret_Gare()

	-- On affiche le résultat
	print("Le nombre de secondes écoulées entre le Point A et B est de : ", g_Difference)
	
end

-- Le programme se termine

Dans ce 2ème exemple, seul le code Lua des lignes 10 à 12 sera exécutée directement. Les fonctions, quant à elles, seront appelées et exécutées uniquement lorsqu'un véhicule franchira les contacts avec les noms des fonctions ajoutés dans la fenêtre des propriétés des contacts (hormis la fonction principale EEPMain() appelée 5 fois par seconde). Tant que le projet sera actif en 3D, c'est-à-dire en mode de conduite automatique ou manuel, ces trois fonctions pourront être appelées autant de fois et aussi longtemps que nécessaire par un véhicule.

Note : Dans le 2ème exemple, on suppose qu'il ne s'écoulera pas plus de 60 secondes entre les appels des fonctions fnc_Debut et fnc_Fin.
Quand faut-il employer une fonction ?

La réponse à cette question est : toute action nécessaire dont la réalisation dans le temps est inconnue. A l'opposé, la déclaration des variables et des constantes pour les besoins du programme s'effectue dès le passage en mode 3D car nous savons avec certitude que ce code doit être exécuté une seule fois. En effet, les variables globales ne peuvent être déclarées qu'une seule fois.

C'est quoi les arguments entre parenthèses ?

Avant de répondre à cette question, il convient d'apporter de la clarté pour éviter une certaine confusion :

  1. Les mots entourés de parenthèses après le nom de la fonction s'appellent des arguments et non des variables ! même si on peut placer des variables utilisées dans la fonction appelante entre les parenthèses lors de l'appel de la fonction !
  2. Les noms des arguments peuvent être différents entre l'appel de la fonction et les arguments entre parenthèses de la fonction appelée même s'ils récupèrent les mêmes valeurs !

Une fonction accepte deux comportements concernant les arguments entre parenthèses :

  1. N'accepter aucun argument,
  2. Accepter un ou plusieurs arguments.

Le cas le plus simple est la fonction sans argument. Exemple :

-- Fonction sans argument : les parenthèses sont vides.
function fnc_Debut()

	-- Prise en compte du temps au point A
	g_Debut_A = EEPTimeS
	
end

La fonction est appelée par un point de contact, elle exécute le code dans ce qu'on appelle le corps de la fonction (ligne n° 5) et elle se termine par le mot clé end à la ligne n° 7.

La fonction avec un ou plusieurs arguments peut être une fonction EEP ou une fonction utilisateur.

Ci-dessous, quelques fonctions EEP contenant des arguments :

  1. EEPRegisterRailTrack(ID) : un argument
  2. EEPSetSignal(ID, Position, Callback) : trois arguments
  3. EEPGoodsSetRotation("#Nom_Lua", PosX, PosY, PosZ) : quatre arguments

Chaque argument est séparé par une virgule !

Dans le cas d'une fonction utilisateur, c'est vous qui créez la fonction et décidez du nombre d'arguments nécessaires en fonction de vos besoins ou du travail censé être accompli par la fonction.

On l'appelle fonction utilisateur parce qu'elle est justement créée par l'utilisateur lui-même, ce qui permet de la différencier avec les fonctions EEP ou les fonctions du langage Lua. Il existe deux mécanismes d'appel pour les fonctions utilisateurs dans EEP :

  1. Les fonctions appelées à partir d'un contact,
  2. Les fonctions appelées à partir d'une autre fonction.

Voici un exemple d'une fonction utilisateur appelée à partir d'un point de contact :


function fnc_Commute_Parcours(Nom_du_Train, Numero_Voie)

	-- Récupère le nom du wagon prêt à être détaché du train
	local l_strNom_Wagon = EEPGetRollingstockItemName(Nom_du_Train, 0)
	-- Récupère la catégorie du wagon prêt à être détaché du train
	local l_strCateg_Wagon = string.sub(l_strNom_Wagon, string.find(l_strNom_Wagon, "%a+"))
	
	ok, Vitesse_Wagon = EEPGetTrainSpeed(Nom_du_Train)
	print("(fnc_Commute_Parcours) Nom_du_Train --> ", Nom_du_Train)
	print("Vitesse matériel roulant --> ", Vitesse_Wagon)

	print("Parcours attribué --> ", g_tblRepart_Wagon[l_strCateg_Wagon][3])

	EEPSetSignal(26, g_tblRepart_Wagon[l_strCateg_Wagon][3]+1)
	-- Incrémente le nombre de wagons triés pour une catégorie donnée
	g_tblRepart_Wagon[l_strCateg_Wagon][4] = g_tblRepart_Wagon[l_strCateg_Wagon][4] + 1
	print("------------------------------------------")

	result = EEPSetTrainName(Nom_du_Train, "#"..string.random(12))

end

Il est écrit dans le manuel Lua qu'une fonction utilisateur appelée à partir d'un contact permet de récupérer en premier argument le nom du train ou du véhicule franchissant le contact et en deuxième argument le numéro ID de la voie ou est posé le contact.

Dans l'exemple ci-dessus, on récupère le nom du train dans le premier argument Nom_du_Train de la fonction à la ligne n° 2. Ensuite on peut utiliser à volonté cet argument comme c'est le cas aux lignes n° 5, 9, 10 et 20. Le nom des arguments n'a que peu d'importance, Nom_du_Train ou Truc_Machin_Chose ou Bidule contiendra toujours le nom du train. Vous pouvez omettre le deuxième argument Numero_Voie si vous n'en avez pas l'utilité. Par contre si vous désirez récupérer uniquement l'ID de la voie, il faut indiquer les deux arguments.

Maintenant nous allons analyser une fonction utilisateur appelée à partir d'une autre fonction et non pas directement d'un contact.

Important : Dans l'exemple ci-dessous, ne vous focalisez pas sur les mots clés que vous ne connaissez peut-être pas. Le but ici est de démontrer la relation entre les différentes fonctions. Les mots clés utilisés seront détaillés dans les autres chapitres consacrés aux fonctions Lua dans EEP.

-- Fonction EEPOnSignal (mais pourrait être une autre fonction utilisateur quelconque)
function EEPOnSignal_1037(Etat)

  -- Appel et exécute la fonction fnc_Avance_Loc(Sig_Debut, Sig_Fin) à la ligne n° 11
  if Etat == 1 then fnc_Avance_Loc(1038, 1043) end

end

-- Fonction utilisateur appelée à partir de la fonction EEPOnSignal_1037(Etat) à la ligne n° 6
function fnc_Avance_Loc(Sig_Debut, Sig_Fin)

	local l_nbrTempo = 0

	math.randomseed(os.time()) -- Initialise le générateur de nombres aléatoires
	for i = Sig_Debut, Sig_Fin do
		l_nbrTempo = 2 + (math.random(i) / i * 7) -- Valeur arbitraire
		print("Temporisation entre les locs = ", l_nbrTempo)

		-- Appel et exécute la fonction fnc_Temporisation(Duree) à la ligne n° 38
		fnc_Temporisation(l_nbrTempo)
		
		EEPSetSignal(i, CONST_SIG_VOIE_LIBRE)
		
		-- Si le signal suivant est déjà sur Voie Libre alors sortir de la boucle car toutes les locs
		-- ont avancé d'un emplacement sur le faisceau	
		if EEPGetSignal(i) == CONST_SIG_VOIE_LIBRE then
			print("i : ", i)
			break			
		end
			
	end		

end

-- Fonction utilisateur appelée par la fonction fnc_Avance_Loc(Sig_Debut, Sig_Fin)
function fnc_Temporisation(Duree)

	local nbr_Debut = os.clock()
	local nbr_Fin = 0
	while nbr_Fin - nbr_Debut <= Duree do  -- tant que nbr_Fin - nbr_Debut reste inférieur ou égal à Duree         
		nbr_Fin  = os.clock() -- on test le temps écoulé...
		-- et on reboucle tant que nbr_Fin - nbr_Debut est < ou égal à Duree
	end

end

Dans cet exemple nous avons 3 fonctions : une fonction EEPOnSignal_1037 à la ligne n° 3 et deux fonctions utilisateur aux lignes n° 11 et 37. Nous allons avancer pas-à-pas et expliquer les relations existantes entre ces fonctions. Commençons par la première fonction EEPOnSignal_1037 à la ligne n° 3. Cette fonction appelle (depuis la ligne n° 6) la fonction utilisateur fnc_Avance_Loc(Sig_Debut, Sig_Fin) située à la ligne n° 11 ce qui revient à dire que l'exécution du script "saute" directement à la ligne n° 11 :

Listing exemple n° 1 fonction utilisateur dans EEP
Appel de fonctions et transmission des arguments entre parenthèses

La fonction utilisateur fnc_Avance_Loc(Sig_Debut, Sig_Fin) contient deux arguments entourés en violet. Elle est appelée à la ligne 6 à partir de la fonction EEPOnSignal_1037.

Pour appeler une fonction c'est très simple : il suffit d'écrire le nom de la fonction et les arguments correspondants entre parenthèses. Lorsque le programme s'exécute et arrive à la ligne n° 6, il "saute" directement à la ligne n° 11 qui correspond à la première ligne de la fonction fnc_Avance_Loc(Sig_Debut, Sig_Fin) et transmet en même temps les arguments dans l'ordre tel qu'ils sont écrits (voir flèches). Ainsi 1038 est affecté à Sig_Debut et 1043 à Sig_Fin.

A partir de cet instant, nous allons récupérer les valeurs contenues dans Sig_Debut et Sig_Fin et les utiliser par exemple à des fins de calcul ou comme c'est le cas ici dans une boucle :

Listing exemple n° 2 fonction utilisateur dans EEP
Arguments utilisés dans la fonction

Les deux arguments entourés en violet sont utilisés dans l'exécution de la boucle. Dans cet exemple ils contiennent des numéros ID de signalisation, mais ils pourraient contenir n'importe quelles autres valeurs.

Nous remarquons également à la ligne n° 21, un appel à une autre fonction utilisateur fnc_Temporisation(l_nbrTempo) avec un seul argument nommé l_nbrTempo. Cet argument est le résultat d'un calcul à la ligne n° 17. Regardons cette fonction :

Listing exemple n° 3 fonction utilisateur dans EEP

Ici l'argument Duree récupère la valeur de l'argument l_nbrTempo de la ligne n° 21.

Tout ceci est bien beau mais arrivé à la fin d'une fonction, que se passe t'il ?

Comme la dernière ligne s'achève par le mot clé end, la fonction se termine et l'exécution continue à la ligne juste après celle qui a appelée la fonction. Ce qui dans notre exemple donnerait l'ordre suivant :

  1. La fonction EEPOnSignal_1037 appelle la fonction fnc_Avance_Loc à la ligne n° 6,
  2. La fonction fnc_Avance_Loc appelle la fonction fnc_Temporisation à la ligne n° 21,
  3. Le travail de la fonction fnc_Temporisation terminé, le mot clé end de la ligne n° 46 renvoie l'exécution du programme à la ligne n° 22,
  4. Une fois que la fonction fnc_Avance_Loc a elle aussi terminé son travail, le mot clé end de la ligne n° 34 renvoie l'exécution du programme à la ligne n° 7,
  5. Et pour terminer, le mot clé end de la ligne n° 8 termine le cycle là où il avait commencé c'est-à-dire à la fonction EEPOnSignal_1037.

Ci-dessous un petit schéma pour visualiser l’interaction entre ces 3 fonctions :

Listing exemple n° 4 fonction utilisateur dans EEP

Apportons une précision importante concernant les arguments et reprenons l'exemple ci-dessus aux couples de lignes [6 et 11] ainsi que [21 - 37] :

Listing exemple n° 5 fonction utilisateur dans EEP

Dans le premier couple, les arguments de la ligne n° 6 sont des nombres (1038 et 1043. Les arguments (Sig_Debut et Sig_Fin) de la ligne n° 11 récupèrent donc ces nombres. Par contre l'argument l_nbrTempo de la ligne n° 21 est une variable. L'argument Duree de la ligne n° 37 récupère aussi la valeur de cette variable. Nous pouvons donc en déduire deux constations importantes :

  1. Les arguments entre parenthèses peuvent être de types différents : nombre, variable, chaine de caractères, booléen,
  2. Dans le cas d'une variable à transmettre comme argument (ici l_nbrTempo à la ligne n° 21), les noms des arguments peuvent être différents. Il n'y a aucune obligation à écrire les mêmes dans la fonction appelante et la fonction appelée. Veillez tout de même à conserver une certaine cohérence entre les noms des arguments et des variables.
Les arguments sont-ils obligatoires ?

Non, comme nous l'avons déjà vu les arguments ne sont pas obligatoires pour les fonctions utilisateur car Il s'agit tout simplement d'une fonction sans argument. A l'inverse, certaines fonctions Lua et EEP requièrent obligatoirement des arguments lorsqu'elles sont appelées.

Une fonction peut-elle renvoyer une valeur ?

Très bonne question ! Mais oui ! une fonction peut renvoyer une ou plusieurs valeurs. C'est même un des atouts essentiels d'une fonction. Et pour le démontrer, nous allons reprendre l'exemple du petit programme de calcul des secondes entre les deux points A et B avec une fonction qui évalue le temps écoulé en secondes et retourne le résultat à la fonction appelante :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
-- Début du programme
-- Calcul d'un temps de trajet entre un point A et un point B et
-- Affichage de la durée en secondes lorsque le train franchi le point B

clearlog()

-- On déclare les variables
g_Debut_A = nil
g_Fin_B = nil

function EEPMain()
    return 1
end

-- Fonction appelée par un prermier contact
function fnc_Debut()

	-- Affiche l'heure EEP en entier. \n provoque un saut de ligne
	print("\nHeure EEP en cours : ", EEPTimeH, ":", EEPTimeM, ":", EEPTimeS)

	-- Prise en compte du temps au point A
	g_Debut_A = EEPTimeS

	-- \n provoque un saut de ligne
	print("\nDebut en secondes : ", g_Debut_A)
	
end

-- Fonction appelée par un deuxième contact
function fnc_Fin()

	local g_Difference = nil

	-- Prise en compte du temps au point B
	g_Fin_B = EEPTimeS
	print("Fin en secondes : ", g_Fin_B)

	-- Calcul du nombre de secondes écoulées entre les deux contacts
	-- en appelant la fonction fnc_Difference avec deux arguments
	g_Difference = fnc_Difference(g_Debut_A, g_Fin_B)	

	print("Le nombre de secondes écoulées entre le Point A et B est de : ", g_Difference)
	
end

-- Fonction appelée par la fonction fnc_Fin
function fnc_Difference(Debut, Fin)

	local l_Temp_Seconde = nil

	-- Calcul le nombre de secondes écoulées entre le point A et B
	-- B étant franchi après A, la soustraction s'effectue du plus grand au plus petit
	-- Si B est plus petit que A alors une nouvelle minute vient de commencer
	if Fin < Debut then
			l_Temp_Seconde = (60 - Debut) + Fin
		else
			l_Temp_Seconde = Fin - Debut
	end
	
	-- Retourne le résultat à la fonction appelante fnc_Fin
	return l_Temp_Seconde
	
end

-- Le programme se termine

Compter les secondes

Projet de démonstration pour compter le nombre de secondes écoulées entre deux points.

Pour visualiser les résultats, téléchargez le petit projet. Ensuite démarrez la locomotive pour afficher les informations dans la fenêtre d'évènements.

Dans cet exemple, aux lignes n° 7 et 8, on déclare les variables g_Debut_A et g_Fin_B. La fonction fnc_Debut est appelée par l'intermédiaire d'un premier contact et enregistre dans la variable g_Debut_A le nombre de secondes écoulées dans la minute en cours lorsqu'un véhicule franchit le contact.

Vous remarquerez aux lignes n° 19 et 25 l'emploi de \n au début des phrases de la fonction print. Ceci a pour effet d'ajouter un interligne supplémentaire pour aérer le texte.

La fonction fnc_Fin est appelée par un deuxième contact placé un peu plus loin. Etudions là de plus près :

Listing n° 1 fonction en Lua renvoyer une valeur dans EEP

A la ligne n° 32 nous découvrons le mot clé local. A l'inverse des variables globales par défaut, le mot clé du langage Lua local indique que la variable est... locale à la fonction. C'est à dire qu'une fois la fonction terminée, la variable est tout simplement détruite et sa valeur perdue. Dans cet exemple, la variable locale g_Difference est utilisée uniquement pour récupérer le résultat du calcul (retourné par la fonction fnc_Difference) et l'afficher dans la fenêtre d'évènements à l'aide de la fonction print à la ligne n° 42.

Dans notre cas, la valeur de cette variable n'a pas vocation à être gardée durant toute la durée d'exécution d'un projet EEP ce qui explique pourquoi elle peut être locale à la fonction et offrir l'avantage de libérer l'espace mémoire qu'elle occupait une fois la fonction terminée.

La ligne n° 40 est la plus importante pour répondre à la question initiale : une fonction peut-elle renvoyer une valeur ?

Listing n° 2 fonction en Lua renvoyer une valeur dans EEP

Oui car la valeur renvoyée dans la variable g_Difference récupère via le signe = le résultat du calcul de la fonction fnc_Difference.

Le fait d'affecter une fonction à droite du signe = demande à Lua d'appeler en premier cette fonction et de renvoyer ensuite le résultat lorsque la fonction fnc_Difference est terminée dans la variable située à gauche du signe =. Ce résultat pourra ensuite être affiché dans la fenêtre d'évènements par la fonction appelante fnc_Fin à la ligne n° 42.

Maintenant que la fonction fnc_Difference vient d'être appelée, examinons son contenu :

Listing n° 3 fonction en Lua renvoyer une valeur dans EEP

Comme nous l'avons vu plus haut, les valeurs des variables g_Debut_A et g_Fin_B de la ligne n° 40 sont passées aux deux arguments Debut et Fin entre parenthèses (ligne n° 47). A la ligne n° 49, nous déclarons une variable locale l_Temp_Seconde qui nous servira de "stockage" temporaire pour renvoyer la valeur du résultat.

Avant de calculer le nombre de secondes écoulées, il convient de tester deux cas pouvant se présenter. Le test commence à la ligne n° 54 mais avant, analysons les deux cas :

  1. Cas n° 1 : la valeur de l'argument Fin (ex : 50 secondes) est plus grand que Debut (ex : 10 secondes). Le temps de parcours entre les deux contacts sera de 40 secondes. Fin - Debut = 40 secondes. Le résultat du calcul est stocké dans la variable l_Temp_Seconde (ligne n° 57).
  2. Cas n° 2 : la valeur de l'argument Debut (ex 40 secondes) est plus grand que Fin (ex : 30 secondes). Dans ce cas, une minute s'est écoulée durant le temps de parcours du véhicule entre les deux contacts. Il convient donc de prendre en compte la minute écoulée et la convertir en secondes. Le calcul se traduit ainsi : (60 secondes moins 40 secondes = 20 secondes) additionnées à la valeur de l'argument Fin de 30 secondes ce qui nous donne un temps de parcours de 50 secondes au total. Ensuite comme pour le 1er cas, le résultat du calcul est stocké dans la variable l_Temp_Seconde (ligne n° 55).

Avant d'aborder les mots clés if - then - else, faisons un bref retour en arrière. La possibilité de réaliser des tests existe depuis le début de l'ère informatique et constitue une brique essentielle dans la programmation. Si les tests n'étaient pas implémentés, l'informatique telle que nous la connaissons aujourd'hui n'existerait pas !

Alors à notre tour de nous y mettre pour apporter de la flexibilité dans nos scripts !

Le test commence à la ligne n° 54 par l'instruction if et qui se termine par then. Ce qui se traduit par : Si Fin est inférieur à Debut alors. En arithmétique le signe inférieur s'écrit < (à l'inverse le signe supérieur s'écrit >). Si la condition est vraie alors la ligne n° 55 est exécutée et le test se termine directement à la ligne n° 58 et les lignes n° 56 et 57 seront totalement ignorées. Si la condition est fausse alors la ligne n° 55 est ignorée : le mot clé else entre alors en action et la ligne n° 57 est exécutée à la place. Le mot clé else se traduit par sinon.

Listing n° 4 fonction en Lua renvoyer une valeur dans EEP

Reproduisons le cheminement mais traduit en clair : Si fin est inférieur à Debut alors on passe à la ligne n° 55 sinon on passe à la ligne n° 57 ensuite dans les deux cas, la variable l_Temp_Seconde récupère le résultat du calcul et le test prend fin à la ligne n° 58. Après la ligne n° 58 nous continuons le déroulement du programme ce qui nous amène à la ligne 61 et à l'instruction return.

Listing n° 5 fonction en Lua renvoyer une valeur dans EEP

Cette instruction retourne le résultat à la ligne n° 40 de la fonction appellante fnc_Fin et affecte la valeur retournée directement à la variable g_Difference :

Listing n° 6 fonction en Lua renvoyer une valeur dans EEP

Il nous reste à afficher cette valeur avec la fonction print de la ligne n° 42. Ensuite la fonction se termine à la ligne n° 44.

Après avoir démarré le projet, voici une copie d'écran de la fenêtre d'évènements. La locomotive a effectué 4 passages sur les contacts :

Listing n° 7 fonction en Lua renvoyer une valeur dans EEP

Dans chaque rectangle, 4 lignes sont affichées :

  1. La première ligne nous indique l'heure à laquelle la locomotive a franchi le 1er contact,
  2. La deuxième ligne récupère la partie des secondes au passage sur le 1er contact,
  3. La troisième ligne récupère la partie des secondes au passage sur le 2ème contact,
  4. La quatrième ligne affiche le temps écoulé en secondes entre le point A et le point B

Si on examine attentivement le rectangle D, on remarquera le franchissement du premier contact à 50 secondes et le deuxième à 6 secondes. Conformément au test à partir de la ligne n° 54, nous retrouvons notre calcul correct (60 - 50) + 6 = 16 secondes au total.

Fonctions de signalisation

Les fonctions de signalisation agissent directement sur les signaux.

EEPSetSignal()

Syntaxe

Paramètres

Valeur(s) retournée(s)

A partir de

Objectif

EEPSetSignal(ID, Position, Callback)

Deux ou trois

Une

EEP 10.2 plug-in 2 / évolution avec EEP14.1 plug-in 1.

Commande la signalisation

Remarque

  • Le premier argument est une valeur numérique représentant l'ID de la signalisation
  • Le second argument se réfère à la position à adopter par la signalisation. Les valeurs à partir de 1 activent aussitôt le signal correspondant. La valeur 0 fait de sorte que la signalisation adopte le positionnement suivant. Avec la valeur -1 on revient sur la position précédente. Sur les parcours prédéfinis la position 1 correspond à "Voie libre" la position 2 à "Arrêt".
  • Depuis EEP 14.1 un troisième argument facultatif avec la valeur 1 permet de lancer l'exécution de la fonction de rappel EEPOnSignal_x(). Pour cela, la signalisation doit être enregistrée en amont et une action préalablement définie au sein de EEPOnSignal_x(). A utiliser avec précaution ! Le signal doit être enregistré via la fonction EEPRegisterSignal(). (Voir page suivante). Une utilisation incorrecte de cette fonction peut entraîner des boucles infinies.
  • La valeur renvoyée est égale à 1 lorsque la signalisation ainsi que la position souhaitée existent ou égale à 0 si l'un des deux n'a pu être trouvé.

Exemple :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier
clearlog()

function EEPMain()
    return 1
end

-- Positionne la signalisation 0001 sur 2. Peut être « voie libre » ou « arrêt » selon l’ordre
-- de classement des différentes positions disponibles (ordre qui est propre à chaque signalisation)
EEPSetSignal(1, 2)

Avant de passer en mode 3D pour exécuter le script, Quelques explications s'imposent !

Nous avons notre fonction EEPSetSignal(1, 2) à la ligne n° 9. Le premier argument est l'ID de la signalisation. Pour rappel, ce numéro est affiché dans la fenêtre des propriétés du signal et aussi dans la fenêtre 2D en chiffre bleu. Il s'agit d'un numéro unique attribué automatiquement pour ce signal lors de la pose sur votre réseau et il ne pourra jamais y avoir deux signaux avec le même numéro.

Id d'un signal pour fonction Lua EEPSetSignal() dans EEP

Le deuxième argument est le numéro de la Sélection de la position de la signalisation :

Commandes du signal dans EEP

Il est important de bien comprendre cette notion de position car tous les signaux de part leur conception n'ont pas obligatoirement le même nombre de positions et celles-ci ne sont pas toutes nommées à l'identique.

Dans notre exemple, nous avons un signal à 4 feux SNCF de notre ami François mais vous pouvez utiliser un autre signal ferroviaire, seuls les noms et les positions ne seront pas identiques mais le principe reste strictement le même.

Voici la liste de toutes les positions contenues dans le signal 4 Feux SNCF :

  • Position 1 = Halte!
  • Position 2 = Marche normale
  • Position 3 = Ralenti - Stop attendu
  • Position 4 = Stop et ralenti - 15 km/h max
  • Position 5 = Ralenti 15 km/h max
  • Position 6 = Marche 160 km/h max
  • Position 7 = Ralenti - Arrêt court attendu

Pour reprendre l'exemple de notre fonction EEPSetSignal(1, 2) à la ligne n° 9, le premier chiffre correspond à l'ID de la signalisation et le numéro 2 correspond à la position Marche normale dans la liste des positions du signal. Ainsi lors de l'appel de cette fonction, le signal sera commuté sur la position n° 2 (marche normale) quelle que soit sa position antérieure.

Nous allons le vérifier en images :

Signal à l'arrêt avant appel fonction EEPSetSignal(1, 2)
Avant appel de la fonction EEPSetSignal(1, 2)

Si vous activez la fenêtre 3D pour exécuter le script, le signal passera à la position Marche normal (équivalent à la position voie libre dans d'autres signaux) :

Signal à l'état Marche après appel fonction EEPSetSignal(1, 2)
Après appel de la fonction EEPSetSignal(1, 2)

Maintenant si nous avions renseigné 0 au lieu de 2 dans le second argument, c'est-à-dire EEPSetSignal(1, 0), la signalisation commuterait sur la position suivante à chaque appel de la fonction. Ci-dessous le script correspondant :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier

clearlog()

CONST_POSITION_PRECEDENTE = 0

function EEPMain()
    return 1
end

function fnc_MaFonction()

	EEPSetSignal(1, CONST_POSITION_PRECEDENTE)

	print("Point de contact franchi par la locomotive")

end

Et un premier exemple en vidéo pour démontrer ce mécanisme :

Dans cette vidéo, nous avons écrit notre propre fonction fnc_MaFonction() pour commuter le signal sur la position suivante chaque fois que la locomotive franchit le contact. Pour rappel, afin d'éviter un message d'erreur, n'insérez pas les parenthèses après le nom de la fonction dans les propriétés du contact véhicule :

Nom de la fonction dans un contact pour véhicule

L'exemple ci-dessus a commuté chaque position par ordre croissant, nous allons procéder à l'opération inverse et définir une valeur égale à -1 pour commuter chaque position par ordre décroissant. Voici un deuxième exemple en vidéo :

Dans tous les cas si vous voulez vérifier la bonne exécution de la fonction, il suffit de tester la valeur en retour comme le permet notre fonction EEPSetSignal() et enregistrer le résultat dans une variable. Regardez le script ci-dessous :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier

-- Déclare une variable nulle car on ne connait pas encore le résultat de la fonction en retour
g_nbrResultat_Signal = nil

function EEPMain()
    return 1
end

-- Exécute la fonction et récupère le résultat en retour pour le signal n° 1 et la position n° 2
g_nbrResultat_Signal = EEPSetSignal(1, 2)

-- Affiche la valeur du résultat
print("La valeur retournée pour l'exécution de la fonction est : ", g_nbrResultat_Signal )

Activons la fenêtre 3D pour exécuter le script et vérifier le résultat dans la fenêtre d'évènements :

Valeur retournée pour un signal dans EEP

La valeur renvoyée est égale à 1 lorsque la signalisation et la position souhaitée existent. Dans le cas contraire, la valeur serait égale à 0 si l'une des deux n'avait pas été trouvé.

Dans les deux cas, valeur retournée ou pas, l'une ou l'autre de ces deux lignes de code (n° 11 et 14) commuteront le signal quoi qu'il arrive :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier

-- Déclare une variable nulle car on ne connait pas encore le résultat de la fonction en retour
g_nbrResultat_Signal = nil

function EEPMain()
    return 1
end

-- Exécuter soit la ligne 11 ou 14 mais pas les deux en même temps
-- Exécute la fonction pour le signal n° 1 et la position n° 2
EEPSetSignal(1, 2)

-- Exécute la fonction et récupère la valeur en retour pour le signal n° 1 à la position n° 2
g_nbrResultat_Signal = EEPSetSignal(1, 2)
Important : Récupérer une valeur en retour n’empêche pas l'exécution d'une fonction !
A retenir : Peu importe la nature du signal. Que ce soit un signal ferroviaire ou un feu tricolore routier ou encore un signal invisible, la méthodologie à appliquer est toujours la même : regarder la liste des positions du signal et renseigner la bonne position dans le 2ème argument de la fonction EEPSetSignal(numéro du signal, numéro de la position).

Nous aborderons le 3ème argument facultatif de notre fonction EEPSetSignal(1, x, 1) dans le chapitre consacrée à la fonction EEPRegisterSignal() car les deux sont liés.

EEPGetSignal()

Syntaxe

Paramètres

Valeur(s) renvoyée(s)

A partir de

Objectif

EEPGetSignal(ID)

Un

Une

EEP 10.2 plug-in 2

Renvoie l'état en cours d'une signalisation

Remarque

  • L'unique argument est une valeur numérique représentant l'ID de la signalisation.
  • La valeur retournée nous renseigne sur le signal donné. Le nombre renvoi à la ligne correspondante dans la liste des différents signaux possibles pour ladite signalisation. Cette liste de signaux est consultable sous « propriétés de l’objet » de la signalisation.
  • Lorsque cette fonction est utilisée sur un parcours prédéfini, la valeur retournée (à laquelle on retranche 1) nous renseigne sur le parcours Pour lequel la signalisation a donné la « voie libre » (par exemple valeur retournée = 4 le 3ème parcours est ouverte à la circulation)
  • Attention : La fonction EEPGetSignal() ne renseigne sur la nouvelle position définie par un EEPSetSignal() qu'à partir du moment où l‘on se retrouve dans un nouveau cycle EEPMain()
  • La valeur retournée est égale à 0 si la signalisation n'existe pas.

Exemple :


-- Déclare une variable nulle car on ne connait pas encore le résultat de la fonction en retour
g_nbrPosition_Signal = nil

function EEPMain()
    return 1
end

g_nbrPosition_Signal = EEPGetSignal(1)

-- Exemple avec un signal à deux positions
if g_nbrPosition_Signal == 0 then -- Si g_nbrPosition_Signal est = à 0 alors
    print("La signalisation n'existe pas") 
  elseif g_nbrPosition_Signal == 1 then -- Sinon si g_nbrPosition_Signal est = à 1 alors
    print("La signalisation 1 est définie sur voie libre") 
  elseif g_nbrPosition_Signal == 2 then -- Sinon si g_nbrPosition_Signal est = à 2 alors
    print("La signalisation 1 est définie sur arrêt")
  else  -- Sinon g_nbrPosition_Signal est différent de 0, 1 ou 2 alors...
    -- Autres cas...
end  -- Fin du test

Dans le script, nous retrouvons les tests en utilisant les mots clés if - elseif - end que l'on peut traduire par : si - sinon si - fin. Le principe est simple : tester si une valeur correspond à une autre valeur. La comparaison s'effectue généralement entre une variable et un nombre, une valeur booléenne ou une chaine de caractère mais peut également comprendre le résultat d'une fonction. Si une comparaison s'avère exacte le test se termine immédiatement et toutes les autres comparaisons sont purement et simplement ignorées.

Dans notre exemple aux lignes 12, 14 et 16, nous comparons si la variable g_nbrPosition_Signal est égale à une valeur numérique. Dans Lua, la comparaison d'égalité s'écrit avec 2 signes =. Si vous écrivez if variable = nombre then avec un seul signe =, une erreur se produira à l'exécution du script. La ligne n° 18 offre une "porte de sortie" au cas où la valeur stockée dans g_nbrPosition_Signal serait différente de 0, 1 ou 2. Il s'agit de la condition par défaut si au moins une des autres conditions n'est pas remplie.

Nous allons reprendre notre exemple dérivé de la fonction EEPSetSignal() avec la locomotive mais cette fois-ci nous allons ajouter la fonction EEPGetSignal() pour récupérer le numéro de position et ainsi vérifier si EEPSetSignal() fait bien son travail !

EEPGetSignal

Projet de démonstration avec la fonction EEPGetSignal.

Ci-dessous le script en question :

Cliquez sur le bouton à droite pour copier ce code dans le presse-papier

clearlog()

-- On déclare une variable pour récupérer le numéro de la position de la signalisation
g_nbrPosition_Signal = nil

-- On déclare une constante pour le 2ème argument de la fonction EEPSetSignal()
CONST_POSITION_SUIVANTE = 0

function EEPMain()
    return 1
end

-- 1er contact
function fnc_ChangePosition()

  -- Commute la position du signal n° 1 sur la position suivante
  EEPSetSignal(1, CONST_POSITION_SUIVANTE)
	
  print("\nLa locomotive vient de passer sur le contact fnc_ChangePosition")

end

-- 2ème contact
function fnc_AffichePosition()

  -- Récupère la position du signal n° 1 
  g_nbrPosition_Signal = EEPGetSignal(1)

  -- Affiche la position du signal n° 1
  print("La signalisation est commutée sur la position n° : ", g_nbrPosition_Signal)
	
end

Regardons tout ça en vidéo :

Le principe est simple et devrait commencer à vous être familier. Rappelez-vous au début de l'article, toutes les fonctions avec les syllabes Get et Set. Nous pouvons traduire l'action Get par Obtenir ou récupérer une valeur et l'action Set par modifier ou assigner une valeur. Cet exemple est parfait pour le démontrer et la bonne nouvelle concerne aussi toutes les autres fonctions construites sur le même schéma de fonctionnement pour les autres classes d'objets.

EEPRegisterSignal()

Syntaxe

Paramètres

Valeur(s) renvoyée(s)

A partir de

Objectif

EEPRegisterSignal(ID)

Un

Une

EEP 10.2 plug-in 2

Enregistre une signalisation pour la fonction de rappel EEPOnSignal_x()

Remarque

  • L'enregistrement d'une signalisation est obligatoire pour que celle-ci puisse exécuter automatiquement la fonction EEPOnSignal_x() lors des opérations de commutation. Le x à la fin de la fonction EEPOnSignal_x() est à remplacer par le numéro du signal enregistré.
  • L'unique argument est une valeur numérique représentant l'ID de la signalisation.
  • La valeur retournée est égale à 1 si le signal existe ou 0 si le signal n'existe pas.

Exemple :


function EEPMain()
    return 1
end

-- On enregistre la signalisation n° 2 pour activer la fonction de rappel EEPOnSignal_2
EEPRegisterSignal(2)

fonction EEPOnSignal_2(nouvelle_Position) 

  if nouvelle_Position == 1 then
      print("La signalisation n° 2 est définie sur voie libre") 
    elseif nouvelle_Position == 2 then 
    print("La signalisation n° 2 est définie sur arrêt")
  end
 
end

Expliquons simplement la logique de cette fonction liée avec les fonctions EEPOnSignal_x() ou le troisième argument facultatif de la fonction EEPSetSignal(). Supposons que nous voulons être informés du changement de position du signal n° 2. Cette commutation peut s'effectuer à différents moments : soit au détours d'un script, soit une action de l'utilisateur directement sur le signal ou encore à partir d'une liaison avec un autre signal ou aiguillage. Comment le prévoir pour intervenir sur la position du signal afin de reprendre le contrôle à des fins de tests ou tout bonnement modifier la position ? C'est ici qu'intervient l'enregistrement du signal avec la fonction EEPRegisterSignal(2).

Avec cette fonction, nous demandons à EEP : "Tu enregistres le signal n° 2 et tu m'informes à chaque changement de position pour ce signal". Une fois celui-ci enregistré, EEP va surveiller chaque changement de position et va déclencher en retour la fonction de rappel EEPOnSignal_x() pour nous informer que la position vient d'être commutée. Vu qu'on lui demande, il nous informe !

Dans cette fonction EEPOnSignal_x() nous allons pouvoir écrire du code pour agir sur le signal et aussi sur d'autres éléments selon les besoins des situations qui pourraient se présenter.

Pour le moment retenez seulement ceci : pour déclencher la fonction de rappel EEPOnSignal_x(), vous avez besoin d'enregistrer le signal concerné avec la fonction EEPRegistrerSignal(). Un exemple de cette fonctionnalité sera développé dans le chapitre suivant avec la fonction EEPOnSignal_x().

EEPOnSignal_x()

Syntaxe

Paramètres

Valeur(s) renvoyée(s)

A partir de

Objectif

EEPOnSignal_x(Nouvelle_Position)

Un

Aucune

EEP 10.2 plug-in 2

Les signaux enregistrés appellent automatiquement cette fonction lorsque leur position change si le signal a été enregistré préalablement avec la fonction de rappel EEPRegisterSignal(ID).
Dans le script, vous définissez et liez la fonction correspondante et déterminez ainsi ce qu'il faut faire lorsque la position du signal change.

Important : Afin d’appeler la fonction de rappel EEPOnSignal_x() au sein de la fonction EEPSetSignal() il est nécessaire de donner la valeur 1 au 3ème paramètre de la fonction EEPSetSignal().

Remarque

  • Le nom de la fonction ne doit pas se terminer par _x mais par l'ID du signal. Pour le signal 0002 par exemple, le nom correct de la fonction serait EEPOnSignal_2().
  • Veuillez noter : Les zéros en tête doivent être omis dans le nom de la fonction !
  • L'argument entre parenthèses est la nouvelle indication donnée par la signalisation sous la forme d'un numéro. Ce numéro fait référence à la place qu'occupe cette indication dans la liste des propriétés de la signalisation. Utilisez une variable de votre choix afin de stocker cette valeur pour une utilisation ultérieure.
  • EEP n'attend aucune valeur en retour lors de l'utilisation de cette fonction.

Exemple :

Dans cet exemple, nous allons découvrir une nouvelle fonction Lua, utiliser un signal routier et compter le nombre de commutation lorsque le signal passe sur Branche principale.

Ici nous avons un feu de circulation routier à quatre positions :

  1. Branche principale, le feu est au vert
  2. Arrêt n° 1 : le feu est au rouge
  3. Arrêt n° 2 : le feu est orange fixe
  4. Vitesse maximale 50 km/h : le feu est orange clignotant.
Cliquez sur le bouton à droite pour copier ce code dans le presse-papier

clearlog()

-- On déclare une variable pour compter le nombre de franchissements du signal
-- si celui-ci est commuté sur Voie libre
g_nbrPassageSignal = 0

-- On déclare une variable pour créer des espaces sur le bord gauche de la
-- fenêtre d'évènements pour l'affichage des phrases
g_strEspace = string.rep ("    ", 3)

-- On déclare une constante pour le 2ème argument de la fonction EEPSetSignal()
CONST_POSITION_SUIVANTE = 0

-- Constantes pour la signalisation
CONST_VOIE_LIBRE = 1
CONST_ARRET = 2
CONST_VIT_MAX_50 = 3
CONST_ORANGE_CLIGNOTANT = 4

function EEPMain()
    return 1
end

-- On enregistre le signal n° 2
EEPRegisterSignal(2)

-- Fonction appelée par un contact
function fnc_ChangePosition()

  -- Commute la position du signal n° 2 à la position suivante
-- Le troisième argument prend la valeur 1 pour déclencher l'appel de la fonction EEPOnSignal_2
  EEPSetSignal(2, CONST_POSITION_SUIVANTE, 1)
	
  print("\n      La voiture vient de passer sur le contact Lua fnc_ChangePosition")

end

function EEPOnSignal_2(new_Position) 

  print(g_strEspace.."la position du signal est le n° : ", new_Position)

  if new_Position == CONST_ARRET then
      print(g_strEspace.."La signalisation n° 2 est définie sur : Arrêt") 
    elseif new_Position == CONST_VOIE_LIBRE then 
      print(g_strEspace.."La signalisation n° 2 est définie sur : Branche principale (= voie libre)")
      -- Totalise le nombre de passage sur la position Branche principale (= voie libre)
      g_nbrPassageSignal = g_nbrPassageSignal + 1
      print(g_strEspace.."Le nombre de commutation sur Branche principale est de : ", g_nbrPassageSignal)      
    elseif new_Position == CONST_VIT_MAX_50 then 
      print(g_strEspace.."La signalisation n° 2 est définie sur : Vitesse maximale 50 km/h (feu orange fixe)")
    elseif new_Position == CONST_ORANGE_CLIGNOTANT then 
      print(g_strEspace.."La signalisation n° 2 est définie sur : feu orange clignotant")
  end
 
end

La fonction EEPOnSignal_2(new_Position) est appelée automatiquement à chaque fois que l'état du signal change. L'argument new_Position de la fonction EEPOnSignal_2 contient le numéro de la position du signal renseigné par EEP. Par conséquent vous ne pouvez pas le modifier. Vous pouvez bien entendu définir un autre nom pour l'argument si vous le désirez mais la valeur elle, n'est pas modifiable.

La ligne n° 10 affiche une nouvelle fonction Lua dénommée string.rep :

Image fonction lua string.rep dans fonction EEPOnSignal

Cette fonction est constituée de deux arguments : le premier concerne la chaine de caractères à répéter et le second le nombre de fois pour la répétition. Dans notre exemple, la chaine avec des espaces sera répétée 3 fois. Lorsque le script va s'afficher dans la fenêtre d'évènements, un décalage vers la droite se produira ce qui nous permettra une mise en forme et une lecture plus aisée. Si par hasard vous voulez diminuer ou augmenter le retrait, il suffit juste de modifier le deuxième argument.

Les constantes sont déclarées aux lignes n° 13 à 18. A la ligne n° 26 se trouve la fonction EEPRegisterSignal(2). Elle permet d'enregistrer le signal n° 2. La déclaration de cette fonction est impérative si on veut déclencher l'évènement EEPOnSignal_2. Si vous n'enregistrez pas au préalable le signal et utilisez la fonction EEPSetSignal avec le troisième argument égal à 1, EEP finira par rentrer dans une boucle infinie car il cherchera un signal non enregistré.

A la ligne n° 29 se trouve la fonction fnc_ChangePosition() :

Image fonction fnc_ChangePosition dans EEPOnSignal_2

Elle fait appel à la fonction EEPSetSignal(2, CONST_POSITION_SUIVANTE, 1) située à la ligne 33. Le troisième argument facultatif est égal à 1 et c'est lui qui déclenche l'appel à la fonction EEPOnSignal_2. Si vous omettez cet argument, la fonction ne sera jamais appelée.

Ensuite vient la fonction EEPOnSignal_2 appelée à chaque changement de position du signal :

Image fonction Lua EEPOnSignal

L'argument new_Position renvoie la position en cours du signal ensuite affiché à la ligne n° 41. Nous retrouvons la variable g_strEspace dans les fonctions print. Les 2 points après la variable ajoute la phrase entre guillemets. Il s'agit de la concaténation de deux phrases pour en former qu'une seule. Si la syntaxe Lua l'avait autorisée, les 2 points auraient pu être remplacés par le signe +.

Les tests permettent d'afficher le numéro de la position courante du signal. Pour rappel avec Lua, le test d'égalité s'écrit avec 2 signes == !

Lorsque le signal commute à chaque fois sur la position Branche principale (égale à Voie Libre dans d'autres signaux), la variable g_nbrPassageSignal est incrémentée de 1 (ligne n° 48) et la valeur est affichée à la ligne n° 49. Ce compteur est là uniquement pour vous montrer comment additionner un chiffre avec Lua. Au premier passage le calcul est : 0 = 0 + 1, au deuxième passage : 1 = 1 + 1 et ainsi de suite.

Ci-dessous, un exemple après quatre passages sur le contact par la voiture :

Image fonction Lua EEPOnSignal fenêtre d'évènements

Comme nous le verrons dans d'autres articles, cette fonction de rappel s'applique également pour d'autres objets et pas que pour les signaux. Ces fonctions permettent d'avoir une grande maitrise sur les opérations de circulation dans un réseau.

EEPGetSignalTrainsCount()

Syntaxe

Paramètres

Valeur(s) renvoyée(s)

A partir de

Objectif

EEPGetSignalTrainsCount(ID)

Un

Une

EEP 13.2 plug-in 2

Renvoie le nombre de véhicules arrêtés au signal spécifié.

Remarque

  • L'argument est l'ID du signal.
  • La valeur retournée est le nombre de trains, voitures, tramways, etc, à l'arrêt devant le signal.
  • Dans EEP est considéré comme un véhicule, tout véhicule qu'il soit attelé ou non (train, voiture, avion, bateau...).

Dans le projet créé pour l'occasion, nous allons étudier plusieurs exemples afin de démontrer le potentiel de cette fonction. Naturellement quelque soit le système de circulation, la procédure est exactement la même.

Exemple :

Dans cet exemple, plusieurs voitures roulent sur une route. Lorsque le feu tricolore va passer au rouge et arrêter les voitures, la fonction nous retournera le nombre de véhicules arrêtés entre le pré-signal et le signal.

Dans l'image ci-dessous, au repère n° 1 nous voyons le premier véhicule, au repère n° 2 se trouve le contact du signal n° 1, au repère n° 3 le pré-signal, au repère n° 4 le contact pour véhicule et au repère n° 5 le signal. La zone de ralentissement commence à partir du pré-signal jusqu'au signal. Il est donc important de placer le contact pour le signal avant le pré-signal et le contact véhicule juste après pour que notre script fonctionne et retourne le nombre de véhicule.

Image exemple fonction Lua EEPGetSignalTrainsCount
Important : Si le contact véhicule est placé avant le pré-signal (repère n° 3), la fonction EEPGetSignalTrainsCount retournera un résultat égal à 0.

Le contact pour signalisation (repère n° 2) n'est pas obligatoire car on aurait très bien pu mettre le signal sur position Arrêt dans la fenêtre de ses propriétés mais très souvent, il est nécessaire d'utiliser un contact pour signalisation en amont du signal.

Le déroulement de l'action est le suivant :

  1. Lorsque le véhicule passe sur le contact signalisation (repère n° 2), celui-ci commute le signal sur Arrêt.
  2. Le véhicule commencera à ralentir à partir du pré-signal (repère n° 3) pour s'arrêter complètement devant le signal,
  3. A chaque franchissement du contact véhicule, la fonction utilisateur fnc_Comptage() du script va être appelée pour afficher le nombre de véhicule(s) arrêté(s) devant le signal.
Cliquez sur le bouton à droite pour copier ce code dans le presse-papier

clearlog()

function EEPMain()
  return 1
end


function fnc_Comptage()

  -- On déclare une variable locale pour récupérer le
  -- nombre de véhicules arrêtés devant le signal n° 1
  local l_Nbr_vehicule = nil

  l_Nbr_vehicule = EEPGetSignalTrainsCount(1)
  
  if l_Nbr_vehicule == 1 then
  
      -- Singulier
      print("Il y a ", l_Nbr_vehicule, " véhicule arrêté devant le signal n° 1")
  
    elseif l_Nbr_vehicule > 1 then

      -- Pluriel  
      print("Il y a ", l_Nbr_vehicule, " véhicules arrêtés devant le signal n° 1")
  
  end 
  
end

Voici le résultat en image :

Image exemple fonction Lua EEPGetSignalTrainsCount en 3D

Nous pouvons compter six véhicules stoppés devant le feu rouge. Le test if - elseif - end à partir de la ligne n° 17 permet d'afficher la phrase (ligne N° 20 ou 25) au singulier ou au pluriel selon le nombre retourné par la fonction EEPGetSignalTrainsCount.

EEPGetSignalTrainName()

Syntaxe

Paramètres

Valeur(s) renvoyée(s)

A partir de

Objectif

EEPGetSignalTrainName(ID, Position)

Deux

Une

EEP 13.2 plug-in 2

Renvoie le nom du véhicule arrêté au signal spécifié selon sa position devant le signal.

Remarque

  • Le premier argument est l'ID du signal.
  • Le deuxième argument est le numéro de position du véhicule à l'arrêt devant le signal
  • La valeur retournée est le nom du véhicule à l'arrêt devant le signal
  • Dans EEP est considéré comme un véhicule, tout véhicule qu'il soit attelé ou non (train, voiture, avion, bateau...).
Exemple :

Nous allons reprendre l'exemple de la fonction précédente et modifier le script pour afficher en plus le nom du véhicule à l'arrêt devant le signal n° 1.

Note : Cette fonction n'est pas opérationnelle à cause d'un bug. Celui-ci a été signalé auprès de l'éditeur. Un exemple sera publié lorsque ce bug sera corrigé.

Conclusion

L'intégration d'un langage de script comme Lua dans EEP est un atout indiscutable et indispensable pour automatiser des tâches plus ou moins complexes dans vos réseaux. Lua pousse beaucoup plus loin les possibilités offertes par l'utilisation des contacts et paradoxalement simplifie la construction des automatismes en évitant de trop surcharger les réseaux par des dizaines de contacts inutiles. Les fonctions Lua pour EEP offre aussi la possibilité d'accéder à certaines fonctions internes du programme et la gestion des objets.

Continuons notre découverte des fonctions Lua pour EEP avec l'article suivant consacré aux aiguillages...

Merci d'avoir lu cet article. Si vous avez des questions ou des suggestions, n’hésitez pas à nous en faire part en bas de cette page en commentaires.

Amusez-vous à lire un autre article. A bientôt !

0 0 votes
Évaluation de l'article
S’abonner
Notification pour
guest
0 Commentaires
Commentaires en ligne
Afficher tous les commentaires
Retour en haut