module inscription newsletter haut de page forum mobile

Rejeter la notice

ateliers live resolve avec forest

Ateliers Live Resolve - Formez-vous en ligne tous les mois avec Forest !
Faites rapidement évoluer la qualité de vos étalonnage avec nos ateliers mensuels de 3h.
Toutes les infos
Rejeter la notice

Nouvelle Formation Prise de son : les inscriptions sont ouvertes !
Maîtrisez la qualité de vos prises de son avec notre formation théorique et pratique de 3 jours ! Du 14 au 16 mai 2024 à Paris.

Lançons-nous dans le scripting !

Discussion dans 'Adobe After Effects' créé par Sequelles, 5 Avril 2006.

Tags:
  1. Julien W.

    Points Repaire:
    1 000
    Recos reçues:
    0
    Messages:
    1 499
    Appréciations:
    +0 / 0 / -0
    Tu passes une fonction en paramètre à sort. Cette fonction sera utilisée pa rsort pour effectuer les comparaisons. Ainsi, tu peux trier tout ce que tu veux, du moment où tu es capable de fournir une fonction de comparaison. Pour comparer deux nombres, c'est trivial, tu peux utiliser les opérateurs < et >. Pour trier des chaînes de caractères, tu as le choix: les trier en fonction de leur longueur? de la somme des valeurs ASCII? La fonction sort ne peut pas deviner la façon dont tu as envie de les comparer, elle te garantie seulement que si tu lui fournis une fonction de comparaison, elle fera ce qui est nécessaire.
    Par convention, comme l'a dit nab, la fonction de comparaison doit retourner un nombre positif si le premier argument se place après le deuxième, ou un nombre négatif si il se place avant. Très simplement, pour trier des nombres selon un ordre croissant, tu peux utiliser la fonction suivante:
    Code:
    function croissant(i, j) { 
        if (i >= j) {
            return 1;
        } else {
            return -1;
        }
    }
    Passer une fonction en paramètre est, en réalité, un concept assez avancé. C'est une propriété bien utile des langages dits fonctionnels. Cependant, de nombreux langages impératifs (comme le javascript ou le C) permettent également de le faire (avec des pointeurs de fonctions, en C).
     
  2. Sequelles

    Sequelles Modérateur
    Modérateur So

    Points Repaire:
    11 780
    Recos reçues:
    20
    Messages:
    4 261
    Appréciations:
    +2 / 13 / -0
    Ca m'échappe un peu... Pour moi un fonction on lui donne des paramètres elle fait son travail et elle renvoie le résultat. Pour utiliser ta fonction pour moi il faudrait indiquer quels sont ces paramètres i et j dont elle a besoin. Donc ce qui me surprend c'est qu'on utilise cette fonction sans préciser les paramètres et automatiquement (est ce que c'est une particularité de la méthode sort ?) sort lui envoie ses couples d’éléments. Autre truc qui me fait bizarre, si on met un chiffre dans les parenthèses après sort, ça ne marche pas. Donc ce qu’on met dans les parenthèses après sort c’est forcement une fonction mais sans préciser les paramètres demandés, et sort test ces couples grâce à ça.
     
  3. Julien W.

    Points Repaire:
    1 000
    Recos reçues:
    0
    Messages:
    1 499
    Appréciations:
    +0 / 0 / -0
    Cet aspect de la programmation fonctionnelle n'est pas évident, c'est normal si tu ne comprends pas tout de suite.
    En programmation fonctionnelle, une fonction est une valeur, tout comme une variable. Regardons un exemple simple. Encore une fois, la syntaxe n'est peut-être pas celle du javascript, que je connais mal, mais devrait te permettre d'en comprendre les grandes lignes.
    Imagine que tu as un tableau, et que tu aimerais écrire une fonction qui retourne la somme de ses éléments.
    Code:
    function sumOfElements(array) {
        sum = 0;
        for (i = 0; i < array.length; i++) {
            sum = sum + array[i];
        }
        return sum;
    }
    
    myArray = new Array(1, 2, 3);
    mySum = sumOfElements(myArray);
    
    Je pense que ce code n'est pas très difficile à comprendre. Maintenant, imagine que tu aimerais écrire une fonction qui retourne la somme du carré des éléments d'un tableau. Comment t'y prendrais-tu? Sûrement comme ceci.
    Code:
    function sumOfSquaredElements(array) {
        sum = 0;
        for (i = 0; i < array.length; i++) {
            sum = sum + array[i] * array[i];
        }
        return sum;
    }
    
    myArray = new Array(1, 2, 3);
    mySumOfSquares =  sumOfSquaredElements(myArray);
    
    Cette solution est parfaitement correcte. Ceci dit, tu remarqueras que la majorité du code est similaire au code précédent. Et si tu aimerais écrire la somme du cube des éléments? La somme de la racine des éléments? La somme des éléments positifs? Comme on l'apprend lors des premiers cours de programmation, la pire des choses est la répétition de code. Comment faire alors? Ce n'est pas évident. D'ailleurs, il n'est pas possible de le faire avec beaucoup de langages. Heureusement, la programmation fonctionnelle nous offre une solution. Vu que toute fonction est une valeur, il est parfaitement légal de passer une fonction en paramètre à une autre fonction. Commençons par écrire la fonction générique.
    Code:
    function sumOfElements(array, function) {
        sum = 0;
        for (i = 0; i < array.length; i++) {
            sum = sum + function(array[i]);
        }
        return sum;
    }
    
    Maintenant, écrivons les fonctions dont on aura besoin.
    Code:
    function dummy(element) {
        return element;
    }
    
    function square(element) {
        return element * element;
    }
    
    function positive(element) {
        if (element > 0) {
            return element;
        } else {
            return 0;
        }
    }
    
    Avec ces fonctions, nous pouvons appeler la fonction générique facilement.
    Code:
    myArray = new Array(1, 2, 3);
    mySum =  sumOfElements(myArray, dummy);
    mySumOfSquares =  sumOfElements(myArray, square);
    mySumOfPositives =  sumOfElements(myArray, positive);
    
    Ce qu'il faut bien comprendre, c'est qu'on passe la fonction en paramètre, et non sa valeur de retour. C'est la différence principale entre ces deux instructions:
    Code:
    myFunction(anotherFunction);
    myFunction(anotherFunction(5));
    Dans la première, on passe la fonction. Dans la seconde, on passe la valeur de retour de la fonction lorsqu'on lui passe 5 comme paramètre -- qui, soit dit en passant, pourrait être une fonction.
    Est-ce que tu comprends un peu mieux?

    PS: Si la programmation fonctionnelle vous intéresse, je vous propose d'essayer Scala, un langage fonctionnel développé dans mon école. Il y a pas mal de documentation sur le site, mais vous pouvez aussi télécharger les transparents du cours ainsi que les exercices et leurs corrigés sur cette page.
     
  4. Julien W.

    Points Repaire:
    1 000
    Recos reçues:
    0
    Messages:
    1 499
    Appréciations:
    +0 / 0 / -0
    En fait, il serait plus propre de séparer la fonction qui s'applique aux éléments de la fonction du prédicat. La fonction générique devrait plutôt s'écrire comme ceci:
    Code:
    function sumOfElements(array, predicat, function) {
        sum = 0;
        for (i = 0; i < array.length; i++) {
            if (predicat(array[i])) {
                sum = sum + function(array[i]);
            }
        }
        return sum;
    }
    La somme des nombres positifs devrait donc utiliser le prédicat. Si on a pas besoin de prédicat, il suffit de passer une fonction qui retourne toujours true.
    Est-ce que les fonctions anonymes existent en javascript? Il semblerait que oui.
    Pour calculer la somme des carrés, on pourrait donc simplement exécuter cette instruction:
    Code:
    myArray = new Array(1, 2, 3);
    mySumOfSquares = sumOfElements(myArray, function(element) { return true; },
        function(element) { return element * element; });
     
  5. Sequelles

    Sequelles Modérateur
    Modérateur So

    Points Repaire:
    11 780
    Recos reçues:
    20
    Messages:
    4 261
    Appréciations:
    +2 / 13 / -0
    C'est à peu près toujours aussi flou pour moi. Je viens juste de taper un bout de code qui fait tout planter ! :bravo:

    Code:
    function maFonction (toto,caca) {
     return 1;
    };
    var tab = ["z","a"]; 
    alert(tab.sort(maFonction));
     
  6. Julien W.

    Points Repaire:
    1 000
    Recos reçues:
    0
    Messages:
    1 499
    Appréciations:
    +0 / 0 / -0
    Ce code est tout à fait correct. Comment l'as-tu testé?

    Pour une introduction théorique à la programmation fonctionnelle, cet article semble relativement complet. Mais ça dépasse totalement le cadre de ce qu'on fait ici (surtout que le javascript n'est pas un langage fonctionnel).

    Par ailleurs, je viens de découvrir un petit "sucre syntaxique" en javascript. Ces deux notations sont identiques:
    Code:
    function name(...) { ... } 
    name = function(...) { ... }
    La deuxième notation met bien en évidence le fait qu'une fonction est une valeur.

    PS: Pour les amateurs de javascript (en dehors du scripting pour After Effects), regardez ceci: MochiKit.
     
  7. Sequelles

    Sequelles Modérateur
    Modérateur So

    Points Repaire:
    11 780
    Recos reçues:
    20
    Messages:
    4 261
    Appréciations:
    +2 / 13 / -0
    Je l'ai testé dans After 7.

    Je laisse de côté pour l'instant cette histoire de fonction utilisée comme une valeur.

    J'ai une question pour nab. Dans le Scripting Guide j'ai trouvé ce qu'il faut pour faire appel aux repères de calque mais rien sur les repères de composition... ?
     
    #52 Sequelles, 15 Avril 2006
    Dernière édition: 15 Avril 2006
  8. nab17connection

    Points Repaire:
    1 900
    Recos reçues:
    1
    Messages:
    1 051
    Appréciations:
    +0 / 0 / -0
    je ne pense pas que cela soit accessible...il faudra passer par un repère de calque
     
  9. Sequelles

    Sequelles Modérateur
    Modérateur So

    Points Repaire:
    11 780
    Recos reçues:
    20
    Messages:
    4 261
    Appréciations:
    +2 / 13 / -0
    Je repars sur autre chose....

    Je n’ai pas beaucoup cherché mais au cas où nab passe par là il pourrait me faire gagner du temps.:D

    Juste pour commencer, comment créer une composition ?

    J’ai trouvé ça dans le Scripting Guide :
    Code:
    app.project.ItemCollection.addComp(name, width, height, pixelAspect, duration, frameRate)
    Je n’arrive pas à l’utiliser. :(
     
  10. Sequelles

    Sequelles Modérateur
    Modérateur So

    Points Repaire:
    11 780
    Recos reçues:
    20
    Messages:
    4 261
    Appréciations:
    +2 / 13 / -0
    hum

    ça c'est mieux:

    Code:
    app.project.items.addComp(name, width, height, pixelAspect, duration, frameRate)
    J'arrive à ajouter le premier item du projet dans la nouvelle comp.
    Code:
    var nouvelleComp = app.project.items.addComp("toto", 500, 500, 1, 30, 24);
    nouvelleComp.layers.add(app.project.item(1))
    :rolleyes:

    Mais imaginons que j'ai trois dossiers A, B et C de métrages dans mon projet
    Chaque dossier contient 500 métrages.
    Je voudrais créer 500 compositions.
    La composition 1 contiendrait le métrage 1 du dossier A, plus le métrage 1 du dossier B plus le métrage 1 du dossier C.
    La composition 2 contiendrait le métrage 2 du dossier A, plus le métrage 2 du dossier B et le métrage 2 du dossier C.
    Etc.
     
    #55 Sequelles, 18 Mai 2006
    Dernière édition: 18 Mai 2006
  11. nab17connection

    Points Repaire:
    1 900
    Recos reçues:
    1
    Messages:
    1 051
    Appréciations:
    +0 / 0 / -0
    oui d'accord, quelle est la question ? :lol:
    tu aimerais simplement etre un peu guidé mais arriver à l'ecrire toi même ou tu préfererais une option plus directe qui consisterait à clicker droit enregistrer sous sur un ptit lien .jsx qui fait ce boulot :D

    c est un script plutot facile...et qui peut te permettre de voir comment utiliser une fonction (tres simple et tres utile), ainsi qu'un mini-bonus que tu n'as jamais du mettre dans tes expressions (car on peut faire autrement) mais qui est une maniere assez elegante de presenter les choses
     
  12. Sequelles

    Sequelles Modérateur
    Modérateur So

    Points Repaire:
    11 780
    Recos reçues:
    20
    Messages:
    4 261
    Appréciations:
    +2 / 13 / -0
    J'aimerais plutôt être guidé et tuyauté pour gagner du temps. Et surtout pratiquer le script. Comme je l'ai dis souvent pour avancer j'ai besoin d'un but et là j'ai envie d'essayer un truc...
    Ce que j'ai décrit est la première étape, la suite c'est que j'ai besoin d'appliquer des expressions à chancun de ces calques. Au final c'est une expérience pour gérer des grosses quantités de calque et utiliser des images de résolutions différentes pour une meilleur gestion des ressources.
    J'y faisait allusion ici :Nouvelle pub Ipod nano
     
  13. nab17connection

    Points Repaire:
    1 900
    Recos reçues:
    1
    Messages:
    1 051
    Appréciations:
    +0 / 0 / -0
    très bien :)

    il faut commencer par récupérer les dossiers "A", "B" et "C" dans des variables: pour cela on devra faire une boucle qui parcourt les items du projet (si le nom de l item est "A" on le stocke...c'est là où se situait le mini-bonus :D, mais tu peux faire ca avec du "if else if...").
    ensuite, faire une autre boucle (i = 1 à "NbD'élementsDansDossier") qui appelle une fonction "createComp". Cette fonction prendra 3 parametres : l'item i de A, l'item i de B et l'item i de C et servira à créer une nlle comp contenant ces 3 éléments ...

    voila en gros

    ps: si tu arrives rapidement à faire cette etape, pour la suite...ajouter une expression sur une propriété --> myLayer.opacity.expression = "random(100);";

    EDIT: ce que je raconte au debut, c'est + pour pratiquer comme tu dis...dans le cas d'un projet qui pourrait contenir d'autres items que les dossiers A, B, C. Pour faire plus court et si tu sais que tu n'auras que ces 3 elements, tu récupères directement l'item par :
    var myFolderA = myProj.item(1);
    Pour accéder aux elements d'un dossier (et c etait peut etre en fait l info qui te manquait), tu utilises "item()" aussi, exemple pour recup le premier metrage du dossier A :
    var myMovie = myFolderA.item(1);
     
    #58 nab17connection, 19 Mai 2006
    Dernière édition: 20 Mai 2006
  14. Sequelles

    Sequelles Modérateur
    Modérateur So

    Points Repaire:
    11 780
    Recos reçues:
    20
    Messages:
    4 261
    Appréciations:
    +2 / 13 / -0
    Je voudrais partir de dossiers sélectionnés plutôt que d’utiliser les noms.
    Mais je ne sais pas si c’est possible en sélectionnant plusieurs dossiers ? ...

    Pour avancer, comme je ne sais pas partir d’une sélection de plusieurs dossiers, je pars sur la sélection d’un dossier principal contenant mes dossiers de métrages.
    J’en suis à faire mes vérifications.

    C’est déjà bien chiant !

    Je veux partir d’un dossier sélectionné, et un seul. Contenant que des dossiers et au moins deux. Et chaque sous-dossiers contenant au moins deux métrages et pas d’autres type d’item.

    J’arrive à un résultat. Pour l’instant si tous est vérifié j’arrive sur l’alert ready

    J’ai rencontré quelques problèmes et j’aurai besoin de tes lumières.
    J’aurais eu besoin d’une procédure pour stopper tout le script dans une boucle quand une condition n’est pas vérifiée. Break me fais juste sortir de la boucle. J’ai donc détourné le problème en vérifiant après le break si la boucle avait été au bout.

    Ensuite je voulais remplir un tableau, mais à deux dimension. Avec en ligne mes dossiers et en colonne mes métrages. Du coup à l’intérieur de cette unique variable je peux appeler le métrage que je veux en indiquant sa ligne et sa colonne. Par exemple myFootages[1][2] me donne le troisième métrage du deuxième dossier. Mais je n’arrive pas à rempli le tableau directement. Si je déclare une variable, maVar, en tant que new Array(), je ne peux pas remplir directement, genre maVar[1][2] = monMétrage. J’ai réussi à contourner le problème en procédant en deux étapes.

    Voilà ç’est un peu fais comme ça, si tu peux jeter un œil pour me donner des conseils.
    Code:
    {
    var theFolder = app.project.activeItem;
    if (!theFolder || !(theFolder instanceof FolderItem))
    	alert("sélectionnez un dossier");
    else {
    	var numFolders = theFolder.numItems;
    	if (numFolders < 2) 
    		alert("ce dossier doit contenir au moins deux sous-dossiers");
    	else {
    		for (var i = 1; i <= numFolders; i++) {
    			if (!(theFolder.item(i) instanceof FolderItem)) {
    				alert("Ce dossier ne doit contenir que des dossiers");
    				break;
    				}
    			}
    		if (i == (numFolders + 1)) {
    			var myFolders = new Array();
    			for (var i = 1; i <= numFolders; i++)
    				myFolders[i-1] = theFolder.item(i);
    			for (var i = 0;  i < numFolders; i++) {
    				if (myFolders[i].numItems < 2) {
    					alert("les sous-dossiers doivent contenir au moins deux métrages");
    					break;
    					}
    				}
    			if (i == numFolders) {	
    				for (var i = 1;  i < numFolders; i++) {
    					if (myFolders[i].numItems != myFolders[i-1].numItems) {
    						alert("les sous-dossiers doivent contenir le même nombre de métrages");
    						break;
    						}
    					}
    				if (i == numFolders) {
    					var numFootage = myFolders[0].numItems;
    					var myFootages =  new Array();
    					for (var i = 0; i < numFolders; i++) {
    						var rowFootage = new Array();
    						for (var j = 1; j <= numFootage; j++) {
    							rowFootage[j-1] = myFolders[i].item(j);
    							}
    						myFootages[i] = rowFootage
    						}
    					var checkFootages = 0;
    					for (var i = 0; i < numFolders; i++) {
    						for (var j = 0; j < numFootage; j++) {
    							checkFootages += !(myFootages[i][j] instanceof FootageItem);
    							}
    						}
    					if (checkFootages > 0)
    						alert ("les sous-dossiers doivent contenir des métrages");
    					else {
    						alert("ready");
    						}
    					}
    				}
    			}
    		}
    	}
    }
     
  15. nab17connection

    Points Repaire:
    1 900
    Recos reçues:
    1
    Messages:
    1 051
    Appréciations:
    +0 / 0 / -0
    oui cela serait effectivement le plus simple dans ton cas...
    tu as l atttribut "selected" qui t indique (true/false) si l'item est selectionne ou non; mais ENCORE MIEUX tu as "selection" qui te stocke direct dans un tableau tous les elements du projet qui sont selectionnés (comme le selectedLayers pour une comp)

    ps: p141 du guide pour l atttribut selection
     
Chargement...
Discussions similaires - Lançons scripting
  1. geoay
    Réponses:
    1
    Nb. vues:
    570

Partager cette page