
Les for loop sont prĂ©sents dans quasiment tout les scripts Harmony. Le role du for loop est de faire “boucler” le bloc de code entre {} un certain nombre de fois.
On s’en sert typiquement pour exĂ©cuter un bloc de code sur chaque Ă©lĂ©ment d’une array.
Ecrivons un script qui met la position en Z de tout les nodes sélectionnés à 0
On pourrait écrire une première version du code comme ceci :
const snodes = selection.selectedNodes()
function set_z_to_zero(_node){
node.setTextAttr(_node,"POSITION.Z",frame.current(),0)
}
set_z_to_zero(snodes[0])
set_z_to_zero(snodes[1])
set_z_to_zero(snodes[2])
set_z_to_zero(snodes[3])
set_z_to_zero(snodes[4])
set_z_to_zero(snodes[5])
set_z_to_zero(snodes[6])
Le problème avec ce code c’est qu’il ne fonctionnera que si l’utilisateur n’a sĂ©lectionnĂ© prĂ©cisĂ©ment que 7 nodes. Il faudrait un code qui fonctionne avec 0 ou plusieurs nodes sĂ©lectionnĂ©s .
On pourra améliorer le code comme ceci :
const snodes = selection.selectedNodes()
function set_z_to_zero(_node){
node.setTextAttr(_node,"POSITION.Z",frame.current(),0)
}
var index = 0
// on test si l'index existes dans l'array snode :
if(typeof arrayName[index] !== 'undefined'){
// il y a un node Ă cet index on peut lui appliquer la fonction
set_z_to_zero(snodes[index ])
}
// on incrémente l'index -> 1
index+=1
if(typeof arrayName[index] !== 'undefined'){
// il y a un node Ă cet index on peut lui appliquer la fonction
set_z_to_zero(snodes[index ])
}
// on incrémente l'index -> 2
index+=1
if(typeof arrayName[index] !== 'undefined'){
// il y a un node Ă cet index on peut lui appliquer la fonction
set_z_to_zero(snodes[index ])
}
// on incrémente l'index -> 3
index+=1
if(typeof arrayName[index] !== 'undefined'){
// il y a un node Ă cet index on peut lui appliquer la fonction
set_z_to_zero(snodes[index ])
}
// on incrémente l'index -> 4
index+=1
if(typeof arrayName[index] !== 'undefined'){
// il y a un node Ă cet index on peut lui appliquer la fonction
set_z_to_zero(snodes[index ])
}
C’est un peu mieux, l’utilisateur peut maintenant sĂ©lectionner entre 0 et 5 nodes et le code ne crash pas car on test Ă chaque foi si l’index existe.
ça fonctionne, mais Normalement vous devriez ressentir une sorte de profond désarroi esthétique en voyant ce code.
Il faudrait que l’utilisateur puisse selectionner autant de nodes qu’il souhaite
Essayons avec le mots clé while.
Le mots-clĂ© while exĂ©cute un bloc de code tant qu’une proposition boolĂ©enne est vrais. Comme dans un if, la proposition boolĂ©enne ou condition se trouve entre parenthèses après le while.
while ( a < b ) {}
Si dans votre description du code vous utilisez le mots “tant que” il est fort probable que vous utiliserez le mots clef “while”
const snodes = selection.selectedNodes()
function set_z_to_zero(_node){
node.setTextAttr(_node,"POSITION.Z",frame.current(),0)
}
// on commence Ă l'index 0 de l'array
var index = 0
// tant que l'index n'est pas égal au dernier index ( nombre d'élément dans l'array -1 )
while (index < snodes.length-1){
// on applique la fonction
set_z_to_zero(snodes[index ])
// on augment l'index pour passer à l'élément suivant
index+=1
}
On gagne tout de suite un peu d’espace mais ça fait encore pas mal de lignes.
Personnellement je dĂ©conseille l’utilisation du mots-clĂ© while car si il y a une erreur dans la condition le code peut facilement boucler Ă l’infini.
Ce code par exemple comptera jusqu’Ă l’infini (enfin jusqu’Ă ce que Harmony crash)
// a ne pas utiliser sauf si vous voulez faire crasher harmony biensur !
var limit = 100
var number = 0
while(limit < 200){ // cette condtion est toujours true car limit ne change pas !
number+=1
MessageLog.trace(number)
}
// la partie du code qui ne sera jamais exécutée car on se sortira jamais de cette boucle while
MessageLog.trace("code finito!")
le mots-clé for
Pour palier aux defaults du while: le for nous permet de boucler mais d’une manière plus contrĂ´lĂ©e ! voici sa syntaxe :
for ( var i = 0 ; i < my_int ; i++ ) {}
const snodes = selection.selectedNodes()
function set_z_to_zero(_node){
node.setTextAttr(_node,"POSITION.Z",frame.current(),0)
}
// on retrouve le code du while mais Ă l'horizontale :
for(var index = 0 ; index < snodes.length ; index++){
set_z_to_zero(snodes[index])
}
On ne peut pas faire plus concis ! 3 lignes
Néanmoins cette syntaxe devrait vous perturber un peu :
des “;” dans des parenthèses ? c’est une sorte de micro code ?
Qu’est ce qui se passe dans ces parenthèses ?
Pour comprendre un for Loop il faut bien comprendre les trois blocs contenus dans ses parenthèses ()
- Bloc Initialisation : on dĂ©clare une variable d’index ( souvent i ) et on lui attribue une valeur de dĂ©part ( souvent 0 ) . C’est une dĂ©claration de variable normale vous pouvez lui donner le nom et la valeur que vous voulez.
- Bloc Condition : fonctionne comme un while , si la condition est true on exĂ©cute le code dans le bloc d’exĂ©cution ainsi que celui contenu entre les {}
- Bloc ExĂ©cution : une ligne de code Ă exĂ©cuter quand la condition est true. Dans 99% des cas le code exĂ©cutĂ© incrĂ©mente l’index (i++)
On commence par l’initialisation puis on exĂ©cute le 3eme bloc et le code entre {} tant que la condition du deuxième bloc est true !
Quelques exemples de ce qu’on peut trouver dans les parenthèses
Initialisation | Condition | Exécution |
(var index = 0 ; | index < 10; | index++) |
(var i = 0 ; | i < arr.length; | i++) |
(var s = 0; | s < snodes.length; | s++) |
(var j = arr.length-1; | j >= 0; | j–) |
Comportement de chaque parenthèses
for 1—> exĂ©cute le code 10 fois |
for 2—> exĂ©cute le code pour chaque Ă©lĂ©ment de l’array |
for 3—> exĂ©cute le code pour chaque node sĂ©lectionnĂ© |
for 4—> exĂ©cute le code pour chaque node sĂ©lectionnĂ© du dernier au premier |
Je vous conseille de tester le code suivant pour bien comprendre le comportement des différents for loop :
const snodes = selection.selectedNodes()
// executer le code X fois
const X = 10
for(var i = 0; i < X ; i++){
MessageLog.trace(i)
}
// parcourir une array en commençant le premier element [0]
for(var i = 0 ; i < snodes.length ; i++){
MessageLog.trace(i)
MessageLog.trace(snodes[i])
}
// parcourir une array en commençant par le dernier element [length-1] et en comptant à rebourt i--
for(var i = snodes.length-1 ; i >= 0 ; i--){
MessageLog.trace(i)
MessageLog.trace(snodes[i])
}
Court-circuiter la boucle : continue et break
Et si le node selectionnĂ© courant snodes[i] n’est pas un PEG ? Si, par exemple il est de type ‘COMPOSITE’
Cela ne nous intĂ©ressera pas de changer sa position en Z car il n’en a pas. Donc nous risquons de perdre une boucle pour rien, et donc de gaspiller des ressources en calcul.
Comment pourrait-on “sauter” cette boucle ?
Comment pourrait-on et passer Ă la boucle suivante si le node n’est pas de type ‘PEG’ ?
const snodes = selection.selectedNodes()
function set_z_to_zero(_node){
node.setTextAttr(_node,"POSITION.Z",frame.current(),0)
}
for(var index = 0 ; index < snodes.length ; index++){
if(node.type(snodes[i])!="PEG"){
// ce n'est pas un peg
}
// essaye quand meme de changer son Z ?
set_z_to_zero(snodes[index])
}
Le mots-clĂ© “continue”
Le mots clĂ© continue dis Ă l’ordinateur ‘pas besoin de lire les lignes suivante , passe Ă la boucle suivante avec une nouvelle valeur d’index (i+1)’ ‘pioche une nouvelle carte’
const snodes = selection.selectedNodes()
function set_z_to_zero(_node){
node.setTextAttr(_node,"POSITION.Z",frame.current(),0)
}
for(var index = 0 ; index < snodes.length ; index++){
// est ce que c'est un peg ?
if(node.type(snodes[i])!="PEG"){
// ce n'est pas un PEG passe Ă la boucle suivante !
continue
}
// c'est un peg tu peux executer la suite du code de la boucle
set_z_to_zero(snodes[index])
}
continue est très puissant pour optimiser un scripte. Il vous entraine aussi Ă bien dĂ©finir les cas oĂą il est utile d’exĂ©cuter une ligne ou non.
Si maintenant j’Ă©cris un for loop qui cherche quelque chose. Mettons le premier node dans la sĂ©lection qui contient la chaĂ®ne de charactères : “HEAD” si je veux trouver le node de la tĂŞte dans un rig.
const snodes = selection.selectedNodes()
var found_node = ""
for(var index = 0 ; index < snodes.length ; index++){
const node_name = node.getName(snodes[i])
if(node_name.indexOf("HEAD")!=-1){
// on a trouvé un node avec HEAD ! on peut ranger son chemin dans la variable 'found_node'
found_node = snodes[i]
}
// on continue Ă chercher meme si on a dit qu'on en voulait qu'un seul
}
Ce code n’est pas très optimal ! est ce que vous comprenez pourquoi ?
Imaginons un pirate qui parcourt une liste de 4 Ă®les pour retrouver son trĂ©sor oubliĂ©. Imaginons qu’il trouve son trĂ©sor dans la deuxième Ă®le mais qu’il continue quand mĂŞme Ă chercher dans les Ă®les 3 et 4 pour voir si le trĂ©sor qu’il vient de trouver ne s’y trouve pas… (oui c’est un pirate fou).

Eh bien ce code se comporte un peu comme le pirate. Il parcourt tout les nodes, mĂŞme si il a trouvĂ© celui qu’il cherchait.
Il faudrait trouver un moyen de lui dire d’arrĂŞter de chercher :
c’est le mots-clĂ© break
const snodes = selection.selectedNodes()
var found_node = ""
for(var index = 0 ; index < snodes.length ; index++){
const node_name = node.getName(snodes[i])
if(node_name.indexOf("HEAD")!=-1){
found_node = snodes[i]
// on a trouvé le node ! tu peux t'arrêter là !
break
}
}
Le mots-clé break permet de sortir de la boucle
Quand l’ordinateur rencontre le mots-clĂ© break dans une boucle il saute directement après le } de la boucle et lit les lignes suivantes du programme. On gagne ainsi en temps d’exĂ©cution ! surtout si quantitĂ© parcourue est grande.
La Notation condensĂ©e ‘for in’
il est possible d’Ă©crire une boucle qui parcourt une array avec une syntaxe encore plus condensĂ©e :
for ( var i in my_array ) {}
Avec ce que nous venons de voir vous devriez comprendre ce que fait le code suivant
const snodes = selection.selectedNodes()
function set_z_to_zero(_node){
node.setTextAttr(_node,"POSITION.Z",frame.current(),0)
}
for(var index in snodes){
set_z_to_zero(snodes[index])
}
Exactement la mĂŞme chose qu’avec un for loop classique !
Attentions cette notation est trompeuse car beaucoup de choses sont implicites :
Ce code parcourt l’array en commençant par l’index 0 et en incrĂ©mentant de 1 jusqu’a la fin de l’array.
Cette notation condensĂ©e existe car c’est le type de for loop qu’on utilise dans la grande majoritĂ© des cas avec une array. Pas besoin d’Ă©crire .length ou i++ : tout est inclu dans le “in” , mais ses possibilitĂ©s sont limitĂ©es !