La digitale, Développement multimédia http://la-digitale.com/ index Système de wiki haxe en Canvas HTML5 : EaselJs en Haxe pour Javasript avec EaselHx http://la-digitale.com/index/html-canvas-test-in-haxe-with-easeljs-easelhx http://la-digitale.com/index/html-canvas-test-in-haxe-with-easeljs-easelhx Thu, 10 Feb 2011 00:16:09 +0100 Thu, 10 Feb 2011 00:16:09 +0100 Julien Beaufils Julien Beaufils <h2>EaselJs</h2> <p><a href="http://easeljs.com/" class="extern">EaselJs </a>est une librairie créée par grant skinner.<br/>Sa principale fonction est de simplifier...</p> <h2>EaselJs</h2> <p><a href="http://easeljs.com/" class="extern">EaselJs </a>est une librairie créée par grant skinner.<br/>Sa principale fonction est de simplifier la gestion de la liste d'affichage, les interactions et les animations simples dans un canvas HTML. <br/>Cette lib déclare des objets bien définis qui seront familliés à certains comme le montre la <a href="http://easeljs.com/docs/" class="extern">doc</a> Elle reste cependant relativement fine. <br/>Le petit outil associé <a href="http://easeljs.com/zoe.html" class="extern">zoë</a> permet (en gros) de convertir des anim flash en objets BitmapSequence d'easelJs.</p> <h2>EaselHx</h2> <p><a href="https://github.com/zjnue/easelhx" class="extern">EaselHx</a> est un dépot git des classes &quot;externs&quot; <a href="http://haxe.org/" class="extern">Haxe</a> permettant d'utiliser EaselJs avec ce language. Ce dépot ne supporte cependant que EaselJs 2.1 alors que la v 3.0 vient de sortir. Cependant le &quot;forker&quot; et ajouter les quelques fonctionnalités manquantes ne doit pas prendre longtemps. <br/>Le fait d'utiliser ce dépot avec EaselJs apporte les avantages supplémentaires suivants : <ul><li>environnement résolument orienté objet relativement propre et évolutif. </li><li>typage stricte avec les vérifications d'incohérences associées à la compilation</li><li>auto-complétion dans les IDE permettant de coder en Haxe comme <a href="http://www.flashdevelop.org" class="extern">FlashDevelop</a></li></ul></p> <h2>Exemple</h2><br/>Pour note et tests personnels j'ai fait un petit exemple absolument pas fonctionnel (un pseudo-carousel).<br/>Bien que la version montrée ici utilise la version 2.1 d'EaselJs et que la lib ait déjà évoluée et gagné en performance, <a href="http://la-digitale.com/file/test-easelhx" class="extern">l'exemple interactif au survol de la souris</a> donne une idée des possibilités, .<br/>Il montre aussi comment retailler à la volée des images trop grandes avant de les montrer dans un contexte animé. <p><b>Remarque : </b>Les images ne sont pas incluses avec les sources, (voir dans la classe &quot;Carousel&quot; pour la nomenclature de nommage)</p> <p><a href="/file/src.zip" class="file file_zip">Sources avec projet FlashDevelop</a><br/><a href="http://la-digitale.com/file/test-easelhx/" class="extern">Exemple en ligne</a> <b>&gt; Passer la souris au dessus du carousel pour l'animer</b></p> CS SDK sous flashdevelop en AS3 pure http://la-digitale.com/index/cssdk-sous-flashdevelop-en-as3-pure http://la-digitale.com/index/cssdk-sous-flashdevelop-en-as3-pure Wed, 26 Jan 2011 22:17:09 +0100 Wed, 26 Jan 2011 22:17:09 +0100 Julien Beaufils Julien Beaufils <h2>CS SDK, Q'uest-ce que c'est : </h2> <p>En 2010, Adobe a sorti une version reforgée du <a href="http://www.adobe.com/devnet/creativesuite/sdk.html" class="extern">CS SDK</a> . <br/>Comme son no...</p> <h2>CS SDK, Q'uest-ce que c'est : </h2> <p>En 2010, Adobe a sorti une version reforgée du <a href="http://www.adobe.com/devnet/creativesuite/sdk.html" class="extern">CS SDK</a> . <br/>Comme son nom l'indique c'est le kit de développent logiciel de la &quot;creative suite 5&quot;. <br/>Il offre un accès profond aux API de la plupart des logiciels CS5 via le language Actionscript 3 en utilisant également le runtime AIR. <br/>On peut ainsi imaginer et développer toute sorte de plugin de la boite de dialogue au tooltip en passant par les panneaux. </p> <p>Malheureusement :<ul><li><a href="http://www.adobe.com/content/dam/Adobe/en/devnet/creativesuite/pdfs/CS_SDK_Guide.pdf" class="extern">le guide du CS SDK</a> explique le fonctionnement avec FlashBuilder4 pour un projet de type MXML uniquement.</li><li>le SDK doit utiliser une version modifiée du SDK Flex antérieure à spark :<br/> Si je pense pouvoir réellement apprécier les composant spark, je sais que ne supporte pas ceux de l'espace de nom mx. En générale l'AS3 me semble suffisant.</li></ul></p> <p>J'ai donc voulu voir si l'on pouvait faire fonctionner ce SDK avec Flashdevelop et ai noté la démarche sur windows 7.<br/><h2>Configuration préalable : </h2><br/>La doc indique qu'il faut faire quelques configs sur son ordi. Elles sont décrites pour les différents windows et mac dans la partie &quot;Running and debugging your extension&quot; du <a href="http://www.adobe.com/content/dam/Adobe/en/devnet/creativesuite/pdfs/CS_SDK_Guide.pdf" class="extern">guide du CS SDK</a></p> <p>Il faut donc :</p> <ul><li>ouvrir l'éditeur de registre de windows ([touche windows]+R, taper regedit et valider) pour y sélectionner le dossier &quot;CSXS2Preferences&quot; et y ajouter un valeur chaine nommée &quot;PlayerDebugMode&quot; avec pour valeur 1.<br/><img src="/file/reg.jpg" alt="reg.jpg" class="intern"/></li><li>ajouter un fichier vide nommé &quot;debug&quot; dans le dossier de l'appli Photoshop dans le cas ou l'on veut faire un plugin pour ce logiciel. (Pour les autres logiciels ce n'est pas nécessaire).</li><li>créer un dossier au nom du projet à débugger dans C:\Users\&lt;user&gt;\AppData\Roaming\Adobe\CS4ServiceManager\extensions\ et y copier le dossier 'CSXS' présent dans le sample &quot;HelloCreativeSuite&quot;</li><li>ouvrir le fichier manifest.xml présent dans 'CSXS', <ul><li>retirer le noeud &quot;ScriptPath&quot; (inutile ici), </li><li>renseigner l'attribut ExtensionBundleId avec un namespace unique pour le plugin (par ex : com.laDigitale.myPlugin) </li><li>renseigner les deux attributs 'id' du champ extension avec le même namespace inspiré du bundleId ( par ex :com.laDigitale.myPlugin.myExtention1 )</li><li>dans le noeud &quot;Lifecycle&quot; ajouter :<br/><pre class="haxe">&lt;StartOn&gt; &lt;Event&gt;applicationActivate&lt;/Event&gt; &lt;/StartOn&gt;</pre></li></ul></li><li>Il faut bien sur également télécharger le <a href="http://www.adobe.com/devnet/creativesuite/sdk/eula_cs5.html" class="extern">CS SDK</a> (lien au pied de la licence.) et le poser dans un endroit cohérent pour y faire référence plus tard.</li></ul> <h2>Configuration de FlashDevelop :</h2> <ul><li>Lancer la dernière release de <a href="http://www.flashdevelop.org/community/viewforum.php?f=11" class="extern">Flashdevelop</a> (3.3.2 pour cet article) </li></ul> <ul><li>Sélectionner project&gt;newProject et créer un projet AS3 de type &quot;AIR AS3 Projector&quot;</li><li>aller dans project&gt;properties<ul><li>dans l'onglet &quot;output&quot; champ &quot;output file&quot;, rechecher le dossier dans lequel a été mis le dossier CSXS et nommer le fichier de sortie dans ce dossier &quot;Main.swf&quot; (en cohérence avec le contenu du fichier &quot;manifest.xml&quot;)</li><li>dans l'onglet &quot;classpath&quot; cliquer sur &quot;add classpath&quot; et rechercher le dossier contenant la <a href="http://www.adobe.com/devnet/creativesuite/sdk/eula_cs5.html" class="extern">CS SDK</a> téléchargée précédemment pour y sélectionner le sous-dossier CreativeSuiteSDK/libs</li><li>dans l'onglet &quot;compiler options&quot; champs &quot;custom path to Flex SDK&quot; rechercher à nouveau le dossier contenant le CS SDK pour y sélectionner le dossier &quot;CreativeSuiteSDK/CS Flex SDK 3.4.0&quot;</li><li>cliquer sur ok pour valider</li></ul></li><li>dans le pannneau &quot;project&quot; une série de lib doit avoir apparue dans un petit dossier ressemblant à un légo et nommé &quot;libs&quot;<ul><li>faire un clic-droit sur &quot;apedelta.swc&quot; et sélectionner &quot;add to library&quot; </li><li>faire un deuxième clique droit et cliquer sur &quot;options&quot; pour passer cette lib en mode &quot;external&quot;</li><li>ajouter également &quot;csawlib.swc&quot; et toute autre lib qui peut être nécessaire (ex : csaw_photoshop.swc pour utiliser les API's de Photoshop) mais en gardant les options par défaut ( inclusion des classes référencées dans le code )</li></ul></li></ul> <ul><li>Ecrire un peu de code dans le fichier &quot;Main.as&quot; du projet<br/><pre class="haxe"><span class="kwd">package</span> <span class="op">{</span> <span class="kwd">import</span> flash<span class="number">.</span>display<span class="number">.</span>Sprite; <span class="kwd">import</span> com<span class="number">.</span>adobe<span class="number">.</span>csawlib<span class="number">.</span>photoshop<span class="number">.</span>Photoshop; <span class="kwd">import</span> com<span class="number">.</span>adobe<span class="number">.</span>photoshop<span class="number">.</span>Application; <span class="comment">/** * ... * @author Julien BEAUFILS */</span> <span class="kwd">public</span> <span class="kwd">class</span> Main <span class="kwd">extends</span> Sprite <span class="op">{</span> <span class="kwd">public</span> <span class="kwd">function</span> Main<span class="op">(</span><span class="op">)</span>:void <span class="op">{</span> <span class="comment">//Pour voir si le panneau est affiché correctement</span> graphics<span class="number">.</span>beginFill<span class="op">(</span>0x00ff00<span class="op">)</span>; graphics<span class="number">.</span>drawRect<span class="op">(</span><span class="number">0</span>, <span class="number">0</span>, <span class="number">100</span>, <span class="number">100</span><span class="op">)</span>; graphics<span class="number">.</span>endFill<span class="op">(</span><span class="op">)</span>; <span class="comment">//Récuperer l'app Photoshop et y ajouter un document</span> <span class="kwd">var</span> app:Application = Photoshop<span class="number">.</span>app; app<span class="number">.</span>documents<span class="number">.</span>add<span class="op">(</span><span class="op">)</span>; <span class="op">}</span> <span class="op">}</span> <span class="op">}</span></pre></li></ul> <ul><li>Compiler avec F8 (pas ctrl+Enter) </li><li>dans le menu &quot;debug&quot; sélectionner &quot;Start a remote session&quot;</li><li>Lancer photoshop et observer le module se lancer immédiatement</li><li>fermer le panneau du module (pas Pquand les tests sont terminés</li><li>modifier et re-compiler </li><li>donner le focus à Photoshop</li><li>Le plug se relance en prenant en compte les modification apportées</li></ul> <h2>Prêt à mélanger la plateforme Flash et les outils de la CS</h2> <p>Ce teste fonctionne sous Photoshop 32Bit mais il ne sera pas possible de débugger avec la version 64 bit : le débugger déclenchera systématiquement une exeption.<br/>S'il n'est pas nécessaire de redémarrer Photoshop, des tests similaires avec Illustrator ont fon,ctionné à l'inverse. L'événement d'activation auuto ne sembe pas être reçu non plus par le panneau (tous les logiciels ne le reçoivent pas).</p> <p>Pour le debugger par contre c'est très chouette : <ul><li>les traces remontent bien dans la fenêtre output de Flashdevelop, </li><li>les Exceptions d'exécution s'affichent correctement :<ul><li>on peut cliquer sur les fonctions dans la pile associée à l'erreur, </li><li>on est alors &quot;envoyé&quot; aux lignes de programme associées dans la sourcer. </li><li>on y voit les valeurs courants des variables en passant à la souris au dessus de leur nom dans le code. </li><li>on peut alors inspecter le contenu de ces variables de façon &quot;récursive&quot;.</li></ul></li></ul></p> <p>Pour le reste, il y a vraiment beaucoup à faire, je pense :<ul><li>Automatisations de tout poil, </li><li>graphisme génératif,</li><li>liaisons entre logiciels (endo ou exo CS5), </li><li>utilisations de services web connus (traduction de texte, recherche spécialisée d'images en fonction de couleur : flick...) ou dédiés (process d'export et d'envoi de contenu à l'extérieur...).<br/></li></ul></p> AS3 : Tests unitaires Asynchrones http://la-digitale.com/index/as3-tests-unitaires http://la-digitale.com/index/as3-tests-unitaires Sun, 16 Jan 2011 17:14:14 +0100 Sun, 16 Jan 2011 17:14:14 +0100 Julien Beaufils Julien Beaufils <h2>Contexte</h2><br/>Hormis l'ajout API'S, le langage AS3 n'a pas beaucoup évolué depuis FP9.<br/>je crois que j'ai ... <h2>Contexte</h2><br/>Hormis l'ajout API'S, le langage AS3 n'a pas beaucoup évolué depuis FP9.<br/>je crois que j'ai eu assez le loisir de le triturer dans tout les sens, de faire et refaire un certain nombre d'erreurs. <p>J'ai notamment eu l'occasion :<ul><li>d'user des <a href="http://en.wikipedia.org/wiki/Design_Patterns" class="extern">design patterns</a> (en particulier les <a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612" class="extern">pricipaux GOF</a>) jusqu'au non sens.</li><li>de programmer à la mode événementielle et sur-dynamiquement jusqu'à l'indébuggabilité voir l'étouffement du programme</li><li>de me retrouver avec des memory leaks de trois mètre de long</li><li>de réécrire des centaines de fois (des milliers ?), la même chose façon anti-<a href="http://fr.wikipedia.org/wiki/Ne_vous_r%C3%A9p%C3%A9tez_pas" class="extern">DRY</a></li><li>de faire de progs nécessitant des configs absolument phénoménales pour afficher 3 images<br/> (<a href="http://en.wikipedia.org/wiki/Convention_over_configuration" class="extern">CoC</a>) </li><li>de coder complètement au feeling ne sachant pas ce que j'allais réaliser : la prog. en écriture automatique.</li></ul></p> <p>Ce genre d'erreur influence la manière que l'on a de programmer.<br/>Parfois je tente de fixer le style courrant avec un petit framework utile pour un certain type de projet. <br/>De temps en temps, en fonction du vent, de la mode et de ce que font les autres, ce framework reste, évolue, grossi, se dégraisse, ou disparait.</p> <p>Après quelques essais je pense que les tests unitaires sont vraiment un très bon outils pour optimiser ce processus.<br/>Je les ai longtemps laissés de coté pour ne pas m'encombrer de lignes de code &quot;inutiles&quot;.<br/>Après essais, je sais que ce n'est pas pour tout de suite en mode &quot;production&quot;. <br/>Cela change cependant réellement l'approche de la prog et m'est quand même utile dès a présent.</p> <h2>Première expérience pratique avec les tests unitaires </h2><br/><h3>Coder les tests avant le programme lui même, logique non ?</h3><ul><li>C'est vraiment quelque chose de positif. </li><li>Cela force a réfléchir à ce que le programme doit faire avant de l'écrire.</li><li>J'ai quand même tendance à écrire au-moins un premier jet d' interface, ensuite j'écris la classe de test en essayant de viser les erreurs types qui peuvent être rencontrées (par exemple pour un &quot;stepper&quot; allant de 0 à n, se retrouver avec un compteur &gt; n ou &lt; 0; modifier la valeur de n et re-tester... )</li></ul> <p><h3>Les tests dirigent le développement</h3><br/>C'est une phase créative qui donnes des idées :</p> <ul><li>Si je vois que ça ne colle pas avec la logique d'utilisation que l'écriture des tests fait ressortir, je modifie l'interface </li><li>Je lance les tests et je m'assure que tout plante comme prévu (sauf peut-être l'instanciation).</li><li>je prog. l'implémentation de la classe testée jusqu'à ce que l'ensemble des test soient &quot;OK&quot;.</li><li>Le nombre d'erreurs se réduit progressivement.</li><li>Pendant ce temps il arrive que je m'aperçoive que je n'ai pas prévu un type d'erreur : <br/>Ce n'est pas grave il faut coder un test permettant de le mettre en évidence et corriger le problème.</li></ul> <p><h3>Meilleur qualité du code ?</h3> <br/>Je ne dirais pas que faire des tests entraine forcément la création d'un code de bonne qualité :<ul><li><b>Les tests unitaires ne garantissent pas la performance, ou la lisibilité du code.</b> </li><li>il peuvent attirer l'oeil sur des problèmes de conception.</li><li>On peut obtenir une classe absolument robuste (dans le cas ou les utilisations sont élaborés finement et les erreurs possibles prévues)</li></ul></p> <h3>Evolution</h3> <p>Une classe est soumise à différents types d'évolutions, en particulier : <ul><li>la réutilisation dans un contexte a priori inattendu, </li><li>l'ajout de fonctionnalité(s) </li><li>la factorisation. </li></ul></p> <div class="biglist"><ul><li>Dans le premier cas avec les tests, on se sent vite à l'aise : ça va marcher c'est sur.<br/>Si une erreur apparaît, on réécris un test et corrige le problème lié au contexte qui si il réapparait sera immédiatement mis en évidence par les tests.</li><li>Dans les autres cas, les tests sont la pour alerter si quelque chose se décale au fur et à mesure de l'évolution de ce bloque de programme.</li></ul> </div> <p><h3>Attention :</h3> </p> <ul><li>Je le répète : les tests unitaires ne garantissent pas la performance, ou la lisibilité du code.</li><li>Ils sont eux-même susceptibles de contenir des erreurs.</li><li>Il appartient au développeur de distinguer <b>TOUS</b> les comportements attendus <b>et inattendus</b> </li><li>Le développement dirigé par les tests fait exploser le nombre de lignes à écrire : cela doit s'inscrire sur le long terme pour que ce soit intéressant, et il est parfois difficile de le savoir à l'avance.</li></ul> <p><h2>Tests synchrones et asynchrones avec ASUNIT</h2></p> <div class="biglist"> <ul><li>J'ai choisi d'utiliser <a href="http://asunit.org/" class="extern">ASUNIT</a>, qui fonctionne dans des contextes variés.<br/>Le fonctionnement est assez simple il faut associer les <a href="http://github.com/lukebayes/asunit/zipball/release" class="extern">sources </a> (répetoire as3/src) au projet contenant les classes à tester.<br/>En mode synchrone j'ai suivi <a href="http://www.ruelke.org/blog-entry-127.html" class="extern">cet exemple</a> <br/>En mode asynchrone on peut continuer d'étendre <em>asunit.framework.TestCase</em> <br/>Lors du test et avant chaque appel à une méthode asynchrone il suffit de référencer le retour de la méthode <em>addAsync()</em> quelque part (c'est un fonction) : Le déroulement du test est bloqué tant que cette fonction n'est pas exécutée. On peut ainsi utiliser plusieurs fois <em>addAsync()</em> pour tester un cas d'utilisation complet nécessitant plusieurs appels asynchrones (ex : une pile de chargement )</li></ul> <ul><li><b>Des exemples de tests :</b> <a href="/file/asunit-test.zip" class="file file_zip">asunit-test.zip</a><br/>L'archive contient une classe Stepper et le corps de base d'une pile de chargement (LoadingQueue) façon &quot;interface&quot; (ie : pas d'événementiel ni de callback hormis les événements natifs) codées avec cette méthode. j'ai notamment ajouté après coup l'aspect cyclique optionnel du Stepper. A ce moment c'est très sympa d'avoir de quoi tester. les &quot;TestCase&quot;'s la &quot;TestSuite&quot; et la classe principale de lancement des tests sont inclus. <br/><b>Ce qui a été intéressant ici pour moi ce n'est pas les classes mais la démarche pour les créer</b>.<br/>Maintenant il me faut apprendre à écrire mieux les tests...</li></ul> </div> AS3 : Mon IPod est un touchpad pour PC http://la-digitale.com/index/mon-ipod-est-un-touchpad-pour-pc http://la-digitale.com/index/mon-ipod-est-un-touchpad-pour-pc Sat, 15 Jan 2011 16:40:07 +0100 Sat, 15 Jan 2011 16:40:07 +0100 Julien Beaufils Julien Beaufils <p>En 2010 il y a eu quelques bonnes nouvelles pour la plateforme Flash : </p> <ul><li>la modification de la licen...</li></ul> <p>En 2010 il y a eu quelques bonnes nouvelles pour la plateforme Flash : </p> <ul><li>la modification de la licence d'Apple qui permet l'utilisation du <a href="http://labs.adobe.com/technologies/packagerforiphone/" class="extern">packager for IPhone</a> </li><li>de nouveaux API AIR dans avec la possibilité de <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/desktop/NativeProcess.html" class="extern">lancer des processus natifs</a>, de <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/ServerSocket.html" class="extern">créer des ServerSocket's</a>, et de <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetworkInfo.html" class="extern">récuperer des informations sur le réseau </a></li><li>Flash Player 10.1 notamment les API <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetGroup.html" class="extern">P2P </a>et le <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/ui/Multitouch.html" class="extern">Multitouch</a></li></ul> <p>J'ai souhaité faire une petite app pour mon IPod permettant de contrôler les ordinateurs connectés à mon réseaux local</p> <p>Je voulais : <ul><li>qu'il y ai le moins de configuration possible</li><li>ne pas être tributaire d'un service extérieur</li><li>ne pas être tributaire de ma connexion à internet </li><li>éviter si possible les dangers associés à la transmission</li></ul></p> <p>Du coup j'ai utilisé chacune des possibilités pré-citées pour écrire un programme dont voici <a href="/file/smart-touchpad.zip" class="file file_zip">les sources</a></p> <p>Il y 2 dossier : </p> <div class="biglist"><ul><li>Un dossier <a href="http://fr.wikipedia.org/wiki/C_sharp" class="extern">C#</a> qui ne contient qu'un fichier &quot;Main.cs&quot; qui doit être compilé en un EXE nommé &quot;mouseControl.exe&quot;. Pour cela j'ai utilisé <a href="http://monodevelop.com/" class="extern">monodevelop</a>.<br/>Cet EXE fait appel aux API's de <a href="http://pinvoke.net/default.aspx/user32.mouse_event" class="extern">user32.dll de Windows</a> pour déclencher des action de souris. <br/>A priori on peut se passer de C# en utilisant rundll.exe, mais ça me semblait plus élégant et pratique de faire ainsi. <br/>De plus, c'est la seule partie du programme général qui ne fonctionne que sur Windows :<br/>Pour décliner sur d'autre plateformes il faudra juste réécrire cette partie spécifique et changer d'executable en fonction de la plateforme dans le programme AS3.</li></ul> <ul><li>Un dossier AS3 comprenant les sources utilisées pour générer deux app :<ul><li>Une pour le PC devant être contrôlé :<br/>Le fichier principal, <em>com/laDigitale/display/TouchpadListener.as</em>, est un <em>Sprite</em> devant contenir un <em>TextField </em>nommé &quot;txtHistory&quot;.<br/>Il doit être compilé avec AIR en <a href="http://help.adobe.com/fr_FR/air/build/WS144092a96ffef7cc16ddeea2126bb46b82f-8000.html" class="extern">profil bureau étendu</a> avec l'EXE &quot;mouseControl.exe&quot; inclue en ressource à la racine de l'app.</li><li>Une pour le smartphone servant de touchpad :<br/>Le fichier principal, <em>com/laDigitale/display/Touchpad.as</em>, est un Sprite devant contenir 2 <em>SImpleButton</em>'s nommés &quot;leftDisplay&quot; et &quot;rightDisplay&quot; (clique gauche et droit de la souris) et un Sprite nommé &quot;pad&quot; (mouvements de la souris)</li></ul></li></ul> </div> <p>L' app. pour Smartphone a été testé avec un IPod touch 4g mais doit marcher sur Iphone/Ipad et Android 2.2+<br/>Une fois les deux app compilées, installées et lancées (peu import l'ordre) tout fonctionne sans configuration. <br/>On peu fermer une app ou l'autre puis la ré-ouvrir, les 2 app se reconnectent et on peu surfer et regarder des vidéos à nouveaux à distance.</p> <h2>Conclusion</h2><br/> <div class="biglist"><ul><li>Attention ces source sont juste un &quot;proof of concept&quot; <br/>J'ai essayer de tester/simplifier/montrer la démarche de communication entre un mobile et un pC en AS3 via le WIFI locale.<br/>il n'y a notamment pas la moindre gestion d'erreur. <br/>Par contre chaque élément (classe) joue un rôle précis. il y a peu de fichier (1 par app +2 interfaces +4 fichiers pour gérer les communications P2P, server TCP, process, transmission coté mobile) <br/>Chaque fichier fait entre 15 et 100 lignes.</li></ul> <ul><li>Il y a plein de trucs chouette à faire avec ces API. <br/>Cependant j'espère que les connections P2P en local en mode direct seront implémentées par Flash Player et AIR dans l'avenir et que les API tels que les <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/DatagramSocket.html" class="extern">DatagramSocket</a> marcherons sur les mobiles (voir <a href="http://help.adobe.com/en_US/as3/iphone/WS789ea67d3e73a8b24b55b57a124b32b5b57-7fff.html" class="extern">cette liste</a>).<br/>Cela simplifierais vraiment les choses, avec un fonctionnement vraiment plus rapide et plus de possibilités</li></ul> </div> <p>Voici un petite video très moche. En attendant mieux on peux y deviner le Multitouch et l'instantanéité du déplacement de la souris :<br/><br/> <object width="480" height="360"><param name="movie" value="http://www.dailymotion.com/swf/video/xgpqh6_ipod-touchpad-with-adobe-air-and-c_tech?additionalInfos=0"></param><param name="allowFullScreen" value="true"></param><param name="allowScriptAccess" value="always"></param><embed type="application/x-shockwave-flash" src="http://www.dailymotion.com/swf/video/xgpqh6_ipod-touchpad-with-adobe-air-and-c_tech?additionalInfos=0" width="480" height="360" allowfullscreen="true" allowscriptaccess="always"></embed></object><br /><b><a href="http://www.dailymotion.com/video/xgpqh6_ipod-touchpad-with-adobe-air-and-c_tech">ipod touchpad with adobe air and c#</a></b></p> Snippet AS3 : intégrer les lib JS de son choix dans un SWF http://la-digitale.com/index/workflow-js-avec-flash http://la-digitale.com/index/workflow-js-avec-flash Sun, 19 Dec 2010 15:56:44 +0100 Sun, 19 Dec 2010 15:56:44 +0100 Julien Beaufils Julien Beaufils <p>Par exemple avec la version minifiée de <a href="http://code.jquery.com/jquery-1.4.4.min.js" class="extern">jQuery </a><br/><pre class="haxe"><span class="comment">/* * Dans cet exemple le fichier jquery.js est enre...</span></pre></p> <p>Par exemple avec la version minifiée de <a href="http://code.jquery.com/jquery-1.4.4.min.js" class="extern">jQuery </a><br/><pre class="haxe"><span class="comment">/* * Dans cet exemple le fichier jquery.js est enregistré * au même endroit que la source */</span> <span class="op">[</span>Embed<span class="op">(</span>source=<span class="string">'jquery.js'</span>,mimeType=<span class="string">"application/octet-stream"</span><span class="op">)</span><span class="op">]</span> <span class="kwd">var</span> jqClass:<span class="type">Class</span>; <span class="kwd">try</span> <span class="op">{</span> ExternalInterface<span class="number">.</span>call <span class="op">(</span> <span class="string">"function(){"</span> +<span class="op">(</span><span class="kwd">new</span> jqClass<span class="op">(</span><span class="op">)</span> as ByteArray<span class="op">)</span>.toString<span class="op">(</span><span class="op">)</span> + <span class="string">";}"</span> <span class="op">)</span>; <span class="op">}</span> <span class="kwd">catch</span><span class="op">(</span>e<span class="op">)</span><span class="op">{</span>trace<span class="op">(</span><span class="string">"as3/js error : "</span>+e<span class="number">.</span>toString<span class="op">(</span><span class="op">)</span><span class="op">)</span><span class="op">}</span></pre></p> <p>Exactement de la même manière, pour l'execution de n'importe quelle expression JS sous forme de chaine à la volée, on peut utiliser cette fonction : </p> <pre class="haxe"><span class="kwd">private</span> <span class="kwd">function</span> runJS<span class="op">(</span>expr:<span class="type">String</span><span class="op">)</span>:void <span class="op">{</span> <span class="kwd">try</span> <span class="op">{</span> ExternalInterface<span class="number">.</span>call<span class="op">(</span><span class="string">"function(){"</span> + expr + <span class="string">"}"</span><span class="op">)</span> <span class="op">}</span> <span class="kwd">catch</span><span class="op">(</span>e<span class="op">)</span><span class="op">{</span>trace<span class="op">(</span><span class="string">"as3/js error : "</span>+e<span class="number">.</span>toString<span class="op">(</span><span class="op">)</span><span class="op">)</span><span class="op">}</span> <span class="op">}</span></pre> <p><b>tip :</b> Le JS peut être écrit &quot;inline&quot; dans le code en l'enveloppant dans un XML avec des CDATA.<br/>De cette manière il peut être mis en forme correctement et la colorisation syntaxique s'exprime (sous flashDevelop)</p> <p><b>Avantages :</b> <ul><li>emporter une lib JS sur tous les sites ou le SWF est partagé (attentions au param &quot;allowScriptAccess&quot;)</li><li>compression/décompression des JS automatisée et réduction du nombre de requêtes</li><li>projet réellement orienté flash (peux de HTML) mais devant utiliser des outils js.<br/>je pense aux <a href="http://www.asual.com/swfaddress/" class="extern">SWFAdress</a>, à <a href="http://swffit.millermedeiros.com/" class="extern">SWFFit</a>, à quelques nouveautés HTML5 sur lesquels les développeurs Flash louchent parfois comme <a href="http://www.whatwg.org/specs/web-workers/current-work/" class="extern">les webWorkers</a></li><li>Lib's passées de manière &quot;presque&quot; transparente de projet en projet lorsqu'elles sont déjà compilées dans un SWC, ou un autre type de module (ça peut-être un inconvénient : on oublie ce qu'il y a dans les petites boites qui ici ont une dépendance avec le contexte d'utilisation). <br/>* réutiliser des comportements prévus dans un HTML alternatif (en le parsant et en réutilisant les attributs onclick par exemple)</li></ul></p> <p><b>Inconvénients: </b><ul><li>pour des SWF partagés, on a pas forcément la mains sur &quot;allowScriptAccess&quot; (par exemple filtres auto de certains CMS)</li><li>toujours pour des SWF partagés balancer un JQuery ou un motools dans la nature peut-être intrusif et redondant. (mettre un id unique dans le nom des objets globaux créés par la lib utilisé, developper en mode ninja)</li><li>problèmes de sécurité liées au XSS</li><li>toute modif du JS doit être re-compilée bien sur.</li></ul></p> Cibler Redtamarin avec Flashdevelop http://la-digitale.com/index/redtamarin http://la-digitale.com/index/redtamarin Sun, 19 Dec 2010 11:49:48 +0100 Sun, 19 Dec 2010 11:49:48 +0100 Julien Beaufils Julien Beaufils <h2>Présentation</h2> <p>L'autre Jour je suis tombé sur un projet sympa :<ul><li><a href="http://code.google.com/p/redtamarin/" class="extern">redtamarin</a> est un projet basé sur <a href="http://www.mozilla.org/projects/tamarin/" class="extern">ta...</a></li></ul></p> <h2>Présentation</h2> <p>L'autre Jour je suis tombé sur un projet sympa :<ul><li><a href="http://code.google.com/p/redtamarin/" class="extern">redtamarin</a> est un projet basé sur <a href="http://www.mozilla.org/projects/tamarin/" class="extern">tamarin</a>, le coeur de Flash Player.</li><li>Il permet d'écrire en as3 des outils en ligne de commande cross-plateform.</li><li>L'api (v0.25) est pour l'instant sommaire, mais il promet d'être agrémenté de <a href="http://code.google.com/p/redtamarin/wiki/API" class="extern">toutes les fonctionnalités essentielles</a> dans peu de temps avec la version 0.3</li></ul></p> <p><h2>Configuration avec Flashdevelop</h2></p> <p>Le Wiki n'indique pas comment utiliser Redtamarin avec cet IDE alors j'ai fait une extension ajoutant un projet type correctement configuré.<ul><li>En mode release, (combobox dans la barre d'outils de <a href="http://www.flashdevelop.org/wikidocs/index.php?title=Main_Page" class="extern">Flashdevelop</a>) le projet type publie un exe (<b>Windows uniquement</b>) au nom du projet et lance le test en ligne de commande. </li><li>En mode debug l'exe n'est pas publié et le lancement du test est donc plus rapide.</li></ul></p> <p>Donc pour être près à coder un outils perso télécharger et installer ce fichier <a href="/file/redtamarin0.25.fdz" class="file file_fdz">redtamarin0.25.fdz</a> pour Flashdevelop</p> <h2>Projet exemple</h2><br/><h3>Créer un nouveau projet :</h3> <p> Si l'installation s'est correctement passé (testé sou windows 7 avec install standard de Flashdevelop). Il doit maintenant être possible de créer un nouveau projet ciblant Redtamarin 0.25</p> <p><img src="/file/new-project.jpg" alt="new-project.jpg" class="intern"/></p> <p>Une fois le projet créé, il est près à être compiler et testé &quot;traditionellement&quot; via la commande CTRL+ENTER. Cependant on ne voit pas grand chose car le programme ne fait rien pour le moment. </p> <h3>coder :</h3> <p>Ouvrir le fichier Main.as dans le répertoire des source &quot;src&quot; :<ul><li> L'include sur la ligne 1 est utile lorsqu'on utilise différentes classes :<br/>Pour le moment le compilateur ne vas pas aller chercher les imports touts seul<br/>Il faut référencer manuellement les fichier de classe via la directive &quot;include&quot; avant de pouvoir les référencé par &quot;import&quot;. <br/>j'ai choisit d'écrire ces références dans le fichier &quot;Includes.as&quot; qui n'est pas utilisé dans cet exemple.<br/>Les classe du projet redTamarin sont cependant déjà référencées à l'appel du compilateur.</li><li>Pour tester un premier programme, y coler par exemple le code suivant en ligne 2 (commentaires du fonctionnement dans la source) :<br/><pre class="haxe"><span class="kwd">import</span> avmplus<span class="number">.</span>System; <span class="kwd">import</span> avmplus<span class="number">.</span>File; <span class="kwd">import</span> flash<span class="number">.</span>utils<span class="number">.</span>ByteArray; <span class="comment">//Recupération des arguments dans un tableau</span> <span class="kwd">var</span> args:Vector.&lt;<span class="type">String</span>&gt; = Vector.&lt;<span class="type">String</span>&gt;<span class="op">(</span>System<span class="number">.</span>argv<span class="op">)</span>; <span class="comment">//Comportement si pas (pas assez) d'argument fournis // illustre l'entrée sortie standard</span> <span class="kwd">if</span> <span class="op">(</span>args<span class="number">.</span>length &lt; <span class="number">1</span><span class="op">)</span> <span class="op">{</span> trace<span class="op">(</span><span class="string">"Fichier compresser ?"</span><span class="op">)</span>; args<span class="op">[</span><span class="number">0</span><span class="op">]</span> = System<span class="number">.</span>readLine<span class="op">(</span><span class="op">)</span>; <span class="op">}</span> <span class="kwd">if</span> <span class="op">(</span>args<span class="number">.</span>length &lt; <span class="number">2</span><span class="op">)</span> <span class="op">{</span> trace<span class="op">(</span><span class="string">"Nom du Fichier de sortie ?"</span><span class="op">)</span>; args<span class="op">[</span><span class="number">1</span><span class="op">]</span> = System<span class="number">.</span>readLine<span class="op">(</span><span class="op">)</span>; <span class="op">}</span> <span class="kwd">try</span> <span class="op">{</span> <span class="comment">/* * &gt;Lecteur d'un fichier en argument 1, * &gt;compression "à la flash" * &gt;Ecriture du fichier compressé sur le disqaue à l'adresse fournie en argument 2 */</span> <span class="kwd">var</span> src:<span class="type">String</span> = args<span class="op">[</span><span class="number">0</span><span class="op">]</span>; <span class="kwd">var</span> dest:<span class="type">String</span> = args<span class="op">[</span><span class="number">1</span><span class="op">]</span>; <span class="kwd">var</span> b:ByteArray = File<span class="number">.</span>fileToByteArray<span class="op">(</span>src, false<span class="op">)</span>; b<span class="number">.</span>compress<span class="op">(</span><span class="op">)</span>; File<span class="number">.</span>writeByteArray<span class="op">(</span>dest, b<span class="op">)</span>; <span class="op">}</span> <span class="kwd">catch</span><span class="op">(</span>e:Error<span class="op">)</span> <span class="op">{</span> <span class="comment">//Gestion des erreurs du processus</span> trace<span class="op">(</span>e<span class="op">)</span>; trace<span class="op">(</span><span class="string">"appuyez sur une touche pour terminer"</span><span class="op">)</span>; System<span class="number">.</span>readLine<span class="op">(</span><span class="op">)</span>; <span class="op">}</span></pre></li></ul></p> <h3>Compiler et tester :</h3> <ul><li>Compiler via CTRL +ENTER. Le teste doit se lancer et demander un fichier en entrée à zipper. <br/>Pour simplifier les tests on peu fournir directement les arguments à la commande de test :</li><li>Aller dans le menu Project &gt; properties</li><li>Dans l'onglet courant (output) fieldset &quot;Test Movie&quot; cliquer sur éditer et ajouter la chaine suivant : <br/><pre class="haxe">-- bin/<span class="kwd">in</span>.txt bin/out<span class="number">.</span>txt</pre><img src="/file/project-out-cmd.jpg" alt="project-out-cmd.jpg" class="intern"/></li><li> Penser à ajouter un fichier nommé &quot;in.txt&quot; dans le répertoire bin du projet avant de compiler.</li></ul> <p>Lors des tests ce programme ne posera cette fois pas de question et créera un fichier compressé 'out.txt'</p> <p><h1>Notes en conclusion</h1></p> <ul><li>Flashdevelop est un chouette outils qui permet d'intégrer différent styles de développement.</li><li>Pour créer mon extension je me suis inspiré de celle d' <a href="http://www.flashdevelop.org/community/viewtopic.php?f=20&amp;t=7335" class="extern">azoth</a> qui est u super outil pour utiliser les opcode d'alchemy dans un contexte de développement simple (via un e api de manipulation de la mémoire propre et une post compilaton intégrés dans cette extension)</li><li>L'extension &quot;fdz&quot; que j'ai créé ne permet que l'export pour Windows, mais Redtamarin permet de cibler d'autres plateformes (linux, OSX...) et les script qui le permettent sont fournis avec le <a href="http://code.google.com/p/redtamarin/downloads/detail?name=red_0.2.5.0.234.zip&amp;can=1&amp;q=" class="extern">projet à télécharger</a> (c'est celui que j'ai mis dans l'extension)</li><li><b>Dans le prochain billet montrerais (entre autre) une utilisation possible du programme example</b><br/></li></ul> flash CS5 XFL tip http://la-digitale.com/index/flash-cs5-xfl-tip http://la-digitale.com/index/flash-cs5-xfl-tip Thu, 11 Nov 2010 11:17:12 +0100 Thu, 11 Nov 2010 11:17:12 +0100 Julien Beaufils Julien Beaufils <p>Juste un petit billet pour remettre en avant l'évolution du format de fichier FLA sur flash cs5 et ...</p> <p>Juste un petit billet pour remettre en avant l'évolution du format de fichier FLA sur flash cs5 et les possibilités associées.</p> <h2>Un nouveau format</h2> <p>Désormais, lorsqu'on enregistre un fichier dans l'IDE flash, même si l'extension reste .fla, on crée une archive ZIP contenant :<ul><li>un fichier XFL</li><li>des fichiers XML qui décrivent le doc et la librairie, </li><li>fichiers media (jpg, png...). </li></ul></p> <p>De plus le FLA est enregistrable comme document non compressé. Le projet passe donc de l'état de fichier à celui de dossier.</p> <h2>Versioning et mise à jours de ressources</h2> <p>Cela me semble très positif, même si ce n'est ni parfait, ni trop tôt.</p> <ul><li>On peut versioner efficacement les projets (SVN, GIT)</li><li>On ne réécrit plus un gros fichier tout neuf à chaque changement, </li><li>Le travail à plusieurs peut être optimisé et sécurisé. </li><li>La mise à jour des médias utilisés par le projet est simplifiée:<br/>Un graphiste peu aller remplacer une image ou l'éditer directement avec l'outil de son choix sans ouvrir l'IDE Flash.(Au lieu d'aller y chercher dans la bibliothèque l'image correspondante, cliquer sur propriété, puis sur mettre à jour, chercher l'adresse de la nouvelle image car la correspondance n'existe plus...)</li></ul> <h2>Rein de mieux que le texte</h2><br/>Mais le point que je souhaite mettre en avant est qu'on a désormais un projet modifiable avec un éditeur de code classique. On peut rechercher et remplacer une police ou un jeu de couleurs par exemple. <p>Ci-dessous un exemple de rechercher remplacer sur une couleur. <br/>Dans le cas des couleurs attention cependant au nuancier.<br/><div class="swf" id="swf_1" style="width : 100px">[test.swf]</div><script type="text/javascript" id="js_1">var o = new js.SWFObject('/file/test.swf','swfobj_1',100,100,'9','#FFFFFF');o.write('swf_1');</script>-------------</p> <p><div class="swf" id="swf_2" style="width : 100px">[test2.swf]</div><script type="text/javascript" id="js_2">var o = new js.SWFObject('/file/test2.swf','swfobj_2',100,100,'9','#FFFFFF');o.write('swf_2');</script></p> <p>Bien sur on pouvait déjà rechercher et remplacer des couleurs directement dans l'IDE de Flash, mais ça ne marchais pas avec les filtres. L'outil ne recherchait que les éléments présents sur la scène.</p> <p>C'est désormais réglé en 2 secondes avec un éditeur de code digne de ce nom.</p> <p><h2>Proof of concept</h2></p> <p>Les possibilités qu'offre un format plus ouvert sont claires (notamment en regardant ce que font d'autres logiciels depuis longtemps).<br/>on peut également parcourir les fichiers pour rechercher / agglomérer des infos utiles. <br/>Par exemple extraire les couleurs utilisées dans un document pour en faire une palette disponible dans le nuancier de ce même document. <br/>Pratique pour décliner une charte après une recherche, reprendre un ancien projet, suite à un import d'éléments vectoriels.</p> <p>Voici un EXE illustratif qui tourne à l'aide du runtime AIR 2.0 et permettant de le faire.</p> <p><a href="/file/fla_palette.exe" class="file file_exe">fla_palette.exe</a> </p> <p>En glissant un dossier de projet flash à l'endroit indiqué, le dossier fourni est modifié de manière à indiquer les couleurs présentes dans le nuancier au sein de l'IDE flash.</p> Une perte de mémoire est si vite arrivée http://la-digitale.com/index/addeventlistener-memory-leak http://la-digitale.com/index/addeventlistener-memory-leak Mon, 8 Nov 2010 23:13:04 +0100 Mon, 8 Nov 2010 23:13:04 +0100 Julien Beaufils Julien Beaufils <p>J'ai vraiment peur de l'AS3 parfois. J'ai peur que tout explose d'un coup.<br/>Avant de commencer deux li...</p> <p>J'ai vraiment peur de l'AS3 parfois. J'ai peur que tout explose d'un coup.<br/>Avant de commencer deux liens en rapport direct avec le sujet :<ul><li> <a href="http://en.wikipedia.org/wiki/Memory_leak" class="extern">Memory leak su wikipedia</a></li><li><a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/EventDispatcher.html#addEventListener%28%29" class="extern">La méthode addEventListener sur la doc de l'AS3 / param useWeakReference</a></li></ul></p> <p>C'est partie...</p> <h2>2 tubes à essais + un témoin; un Bec Bunsen !</h2> <p>Prenons par exemple la classe de document test suivante :</p> <pre class="haxe"><span class="kwd">package</span> <span class="op">{</span> <span class="kwd">import</span> flash<span class="number">.</span>display<span class="number">.</span>Sprite; <span class="kwd">import</span> flash<span class="number">.</span>events<span class="number">.</span>Event; <span class="kwd">public</span> <span class="kwd">class</span> MemoryLeaksTest <span class="kwd">extends</span> Sprite <span class="op">{</span> <span class="kwd">public</span> <span class="kwd">function</span> MemoryLeaksTest<span class="op">(</span><span class="op">)</span> <span class="op">{</span> <span class="kwd">new</span> Sprite<span class="op">(</span><span class="op">)</span>.addEventListener <span class="op">(</span> Event<span class="number">.</span>EXIT_FRAME, <span class="kwd">new</span> SetTimeoutTest<span class="op">(</span><span class="op">)</span>.enterFrame, false, <span class="number">0</span>, true <span class="comment">//on utilise les weak référence</span> <span class="op">)</span>; <span class="kwd">new</span> Sprite<span class="op">(</span><span class="op">)</span>.addEventListener <span class="op">(</span> Event<span class="number">.</span>EXIT_FRAME, <span class="kwd">new</span> AnonymousFuncTest<span class="op">(</span><span class="op">)</span>.enterFrame, false, <span class="number">0</span>, true <span class="comment">//on utilise les weak référence</span> <span class="op">)</span>; <span class="kwd">new</span> Sprite<span class="op">(</span><span class="op">)</span>.addEventListener <span class="op">(</span> Event<span class="number">.</span>EXIT_FRAME, <span class="kwd">new</span> NoLeakTest<span class="op">(</span><span class="op">)</span>.enterFrame, false, <span class="number">0</span>, true <span class="comment">//on utilise les weak référence</span> <span class="op">)</span>; <span class="op">}</span> <span class="op">}</span> <span class="op">}</span> </pre> <p>et les classes associées qui se ressemblent beaucoup (le tube témoin et les autres tubes à essais) : </p> <div class="biglist"> <ul><li><h3>NoLeakTest.as</h3> (pas de perte de mémoire)<br/><pre class="haxe"><span class="kwd">package</span> <span class="op">{</span> <span class="kwd">import</span> flash<span class="number">.</span>events<span class="number">.</span>Event; <span class="kwd">import</span> flash<span class="number">.</span>utils<span class="number">.</span>setTimeout; <span class="comment">/** * ... * @author Julien BEAUFILS */</span> <span class="kwd">public</span> <span class="kwd">class</span> NoLeakTest <span class="op">{</span> <span class="kwd">public</span> <span class="kwd">function</span> NoLeakTest<span class="op">(</span><span class="op">)</span> <span class="op">{</span> <span class="op">}</span> <span class="kwd">public</span> <span class="kwd">function</span> enterFrame<span class="op">(</span>e:Event<span class="op">)</span>:void <span class="op">{</span> trace<span class="op">(</span><span class="kwd">this</span><span class="op">)</span>; <span class="op">}</span> <span class="op">}</span> <span class="op">}</span></pre></li></ul> <ul><li><h3>AnonymousFuncTest.as </h3></li></ul> <p>Déclaration d'une fonction anonyme dans une variable local ou de classe, ou comme propriété d'un objet.<br/>Mauvaise pratique connue, parfois tentante et utilisée en interne de librairies populaires, voir même encouragée par l'exemple.</p> <pre class="haxe"><span class="kwd">package</span> <span class="op">{</span> <span class="kwd">import</span> flash<span class="number">.</span>events<span class="number">.</span>Event; <span class="kwd">import</span> flash<span class="number">.</span>utils<span class="number">.</span>setTimeout; <span class="comment">/** * ... * @author Julien BEAUFILS */</span> <span class="kwd">public</span> <span class="kwd">class</span> AnonymousFuncTest <span class="op">{</span> <span class="kwd">public</span> <span class="kwd">function</span> AnonymousFuncTest<span class="op">(</span><span class="op">)</span> <span class="op">{</span><span class="kwd">var</span> func:Function = <span class="kwd">function</span><span class="op">(</span><span class="op">)</span> <span class="op">{</span> <span class="op">}</span>;<span class="op">}</span> <span class="kwd">public</span> <span class="kwd">function</span> enterFrame<span class="op">(</span>e:Event<span class="op">)</span>:void <span class="op">{</span> trace<span class="op">(</span><span class="kwd">this</span><span class="op">)</span>; <span class="op">}</span> <span class="op">}</span> <span class="op">}</span></pre> <ul><li><h3>SetTimeoutTest.as</h3></li></ul> <p>Utilisation de setTimeout pour différer légèrement une action / pour séquencer quelque chose... <br/>C'est tellement tentant.</p> <pre class="haxe"><span class="kwd">package</span> <span class="op">{</span> <span class="kwd">import</span> flash<span class="number">.</span>events<span class="number">.</span>Event; <span class="kwd">import</span> flash<span class="number">.</span>utils<span class="number">.</span>setTimeout; <span class="comment">/** * ... * @author Julien BEAUFILS */</span> <span class="kwd">public</span> <span class="kwd">class</span> SetTimeoutTest <span class="op">{</span> <span class="kwd">public</span> <span class="kwd">function</span> SetTimeoutTest<span class="op">(</span><span class="op">)</span> <span class="op">{</span> setTimeout<span class="op">(</span>func, <span class="number">100</span><span class="op">)</span>; <span class="op">}</span> <span class="kwd">private</span> <span class="kwd">function</span> func<span class="op">(</span><span class="op">)</span>:void <span class="op">{</span><span class="op">}</span> <span class="kwd">public</span> <span class="kwd">function</span> enterFrame<span class="op">(</span>e:Event<span class="op">)</span>:void <span class="op">{</span> trace<span class="op">(</span><span class="kwd">this</span><span class="op">)</span>; <span class="op">}</span> <span class="op">}</span> <span class="op">}</span></pre> </div> <h2>Résultats de l'expérieance</h2> <p>On verras ces deux lignes se répéter en permanence en sortie : </p> <pre class="haxe"><span class="op">[</span>object SetTimeoutTest<span class="op">]</span> <span class="op">[</span>object AnonymousFuncTest<span class="op">]</span></pre> <h3>CE N'EST PAS NORMAL</h3> <ul><li>Les instances ne sont référencées explicitement nulle part dans le code et pourtant elles sont bien là, se nommant en permanence sur la fenêtre de sortie.</li></ul> <ul><li>On aura beau faire du <em>clearTimeout </em>d'un identifiant référencé, passer des variables à <em>null </em>etc... <br/>Le seul moyen de stopper cette sortie est de <b>supprimer les écouteurs explicitement</b>. </li></ul> <ul><li>Les objets n'ont pas quitté la mémoire. <b>la suppression explicite des écouteur est indispensable mais absoluement pas suffisante</b>.</li></ul> <h2>La solution finale</h2> <ul><li>Exterminer les fonctions anonyme (bien que les autres les utilisent).</li><li>Supprimer du vocabulaire <em>setTimeout </em>et <em>setInterval </em>bien qu'on les utilise parfois également sans en avoir conscience.</li><li>Croiser les doigts et tester la mémoire.<br/></li></ul> AS3 : Vie des Objets graphiques / injection de comportements http://la-digitale.com/index/liste-d-affichage-injection-de-comportements http://la-digitale.com/index/liste-d-affichage-injection-de-comportements Thu, 4 Nov 2010 22:02:09 +0100 Thu, 4 Nov 2010 22:02:09 +0100 Julien Beaufils Julien Beaufils <h2>3 Evénements utiles pour la gestion de l'affichage :</h2> <p>Il permettent :</p> <div class="biglist"> <ul><li>d'associer des comportements ...</li></ul></div> <h2>3 Evénements utiles pour la gestion de l'affichage :</h2> <p>Il permettent :</p> <div class="biglist"> <ul><li>d'associer des comportements aux objets graphiques lorsqu'ils sont ajoutés à la liste d'affichage <br/><pre class="haxe">stage<span class="number">.</span>addEventListener <span class="op">(</span> Event<span class="number">.</span>ADDED_TO_STAGE, onAddedToStage, true, <span class="comment">// Utiliser la phase de capture sinon... surprise</span> true <span class="op">)</span>;</pre></li><li>de gérer les relations entre éléments graphiques regroupés dans un <em>DisplayObjectContainer</em> juste avant son rendu :<br/><pre class="haxe">displayContainer<span class="number">.</span>addEventListener <span class="op">(</span> Event<span class="number">.</span>FRAME_CONSTRUCTED, onFrameConstructed, false, <span class="number">0</span>, true <span class="op">)</span>;</pre></li><li>de nettoyer correctement ces comportements lorsque les objets graphiques sont retirés<br/><pre class="haxe">stage<span class="number">.</span>addEventListener <span class="op">(</span> Event<span class="number">.</span>REMOVED_FROM_STAGE, onRemovedFromStage, true, <span class="comment">// Utiliser la phase de capture sinon... surprise</span> <span class="number">0</span>, true <span class="op">)</span>;</pre></li></ul> <p>Un assemblage réfléchi donne une classe utilitaire pour injecter / associer du code aux objets graphiques au bon moment de leur vie.<br/>Des interfaces permettent d'injecter proprement la dépendance logique spécifique à chaque projet (ou au conteneur graphique qui peut-être autre chose que le stage).</p> <pre class="haxe"><span class="kwd">package</span> displayListener <span class="op">{</span> <span class="kwd">import</span> displayListener<span class="number">.</span>interfaces<span class="number">.</span>IDisplayControler; <span class="kwd">import</span> flash<span class="number">.</span>display<span class="number">.</span>DisplayObject; <span class="kwd">import</span> flash<span class="number">.</span>display<span class="number">.</span>DisplayObjectContainer; <span class="kwd">import</span> flash<span class="number">.</span>events<span class="number">.</span>Event; <span class="comment">/** * ... * @author Julien BEAUFILS */</span> <span class="kwd">public</span> <span class="kwd">class</span> DisplayListener <span class="op">{</span> <span class="kwd">private</span> <span class="kwd">var</span> displayContainers:Vector.&lt;DisplayObjectContainer&gt; = <span class="kwd">new</span> Vector.&lt;DisplayObjectContainer&gt;<span class="op">(</span><span class="op">)</span>; <span class="kwd">private</span> <span class="kwd">var</span> displayControler:IDisplayControler; <span class="kwd">public</span> <span class="kwd">function</span> DisplayListener<span class="op">(</span>displayContainer:DisplayObjectContainer, displayControler:IDisplayControler<span class="op">)</span> <span class="op">{</span> <span class="kwd">this</span>.displayControler = displayControler; displayContainer<span class="number">.</span>addEventListener<span class="op">(</span>Event<span class="number">.</span>ADDED_TO_STAGE, onAddedToStage, true, <span class="number">0</span>, true<span class="op">)</span>; displayContainer<span class="number">.</span>addEventListener<span class="op">(</span>Event<span class="number">.</span>FRAME_CONSTRUCTED, onFrameConstructed, false, <span class="number">0</span>, true<span class="op">)</span>; displayContainer<span class="number">.</span>addEventListener<span class="op">(</span>Event<span class="number">.</span>REMOVED_FROM_STAGE, onRemovedFromStage, true, <span class="number">0</span>, true<span class="op">)</span>; <span class="op">}</span> <span class="kwd">private</span> <span class="kwd">function</span> onAddedToStage<span class="op">(</span>e:Event<span class="op">)</span>:void <span class="op">{</span> <span class="kwd">var</span> display:DisplayObject = e<span class="number">.</span>target as DisplayObject; displayControler<span class="number">.</span>ini<span class="op">(</span>display<span class="op">)</span>; <span class="kwd">if</span> <span class="op">(</span>display is DisplayObjectContainer<span class="op">)</span> displayContainers<span class="op">[</span>displayContainers<span class="number">.</span>length<span class="op">]</span> = display as DisplayObjectContainer; <span class="op">}</span> <span class="kwd">private</span> <span class="kwd">function</span> onFrameConstructed<span class="op">(</span>e:Event<span class="op">)</span>:void <span class="op">{</span> <span class="kwd">for</span> each <span class="op">(</span><span class="kwd">var</span> displayContainer:DisplayObjectContainer <span class="kwd">in</span> displayContainers<span class="op">)</span> displayControler<span class="number">.</span>run<span class="op">(</span>displayContainer<span class="op">)</span>; displayContainers<span class="number">.</span>splice<span class="op">(</span><span class="number">0</span>, displayContainers<span class="number">.</span>length<span class="op">)</span>; <span class="op">}</span> <span class="kwd">private</span> <span class="kwd">function</span> onRemovedFromStage<span class="op">(</span>e:Event<span class="op">)</span>:void <span class="op">{</span> displayControler<span class="number">.</span>del<span class="op">(</span>e<span class="number">.</span>target as DisplayObject<span class="op">)</span>; <span class="op">}</span> <span class="op">}</span> <span class="op">}</span></pre> </div> <p><h3>Attention :</h3></p> <p>Les objets du type <em>SimpleButton</em> ont un comportement inattendu du fait que ce ne sont pas des <em>DisplayObjectContainer </em>. Du coup, si un objet (par ex un <em>TextField</em>) créé dans l'IDE FLash à la racine d'un bouton doit absolument être traité, il faudra l'imbriquer dans un clip.</p> <h2>projet Illustratif: </h2> <p>Les fichiers ci-joints montrent un même faux projet codé selon trois approches pour illustrer l'utilité de cette technique :<br/><a href="/file/behaviours-ctrl.zip" class="file file_zip">behaviours-ctrl.zip</a></p> <h3>FromScratchDesign.as </h3> <ul><li>Le programme est écrit d'un coup en une classe sans utiliser le snippet. </li><li>Il est très peu évolutif, bien que ça reste vite fait et fonctionnel.</li><li>le générateur de spaghetti se trouve sur cette ligne (Que ce passe-t-il lorsque &quot;day&quot; deviens &quot;morning&quot; + &quot;afternoon&quot; ): <br/><pre class="haxe"><span class="kwd">if</span> <span class="op">(</span>id == <span class="string">"night"</span><span class="op">)</span> <span class="kwd">var</span> btName:<span class="type">String</span> = <span class="string">"bt_day"</span> <span class="kwd">else</span> btName = <span class="string">"bt_night"</span>;</pre></li></ul> <h3>BetterDesign.as</h3> <ul><li>Toujours en une classe mais en utilisant les événements décrits dans cet article . </li><li>Le code en lui-même reste peu évolutif (voir les switches). </li><li>Cependant les données et le graphisme associés peuvent sensiblement évoluer sans toucher au code.</li></ul> <h3>OODesign.as</h3><br/>Le nombre de classes associées est complètement sur-dimensionné pour ce petit projet virtuel. <p><b>Cependant : </b><ul><li>Un cadre est &quot;posé&quot; par l'intermédiaire d'interfaces.</li><li>Le couplage entre chaque classe est faible (interfaces + classes de bases de type DisplayObject/Event...).</li><li>Toutes les créations d'instances (sauf pour un vecteur privé) se font dans cette classe principale. </li></ul></p> <p><b>Il en résulte que :</b><ul><li>Le code est &quot;bidouillable&quot; à souhait .</li><li>L'ajout de types de comportement est simplifié.</li><li>La réutilisation des codes dans des contextes différents est simplifiée.</li></ul></p> la-digitale.com http://la-digitale.com/a-propos/la-digitale.com http://la-digitale.com/a-propos/la-digitale.com Sun, 17 Oct 2010 15:43:08 +0200 Sun, 17 Oct 2010 15:43:08 +0200 Julien Beaufils Julien Beaufils <h2>Qui</h2><ul><li><a href="http://ladigitale.com/wiki/user?name=ladigitale/" class="extern">Julien BEAUFILS</a></li><li><b>Expert ActionScript 3</b></li><li><b>Développeur multimédia</b> pour le compte de <a href="http://supersoniks.com" class="extern">SUPERSONIKS</a></li><li>Un peu ...</li></ul> <h2>Qui</h2><ul><li><a href="http://ladigitale.com/wiki/user?name=ladigitale/" class="extern">Julien BEAUFILS</a></li><li><b>Expert ActionScript 3</b></li><li><b>Développeur multimédia</b> pour le compte de <a href="http://supersoniks.com" class="extern">SUPERSONIKS</a></li><li>Un peu <a href="http://fr.wikipedia.org/wiki/Nerd" class="extern">n3rd</a>, un peu <a href="http://www.domain.com" class="extern">geek</a></li><li>Ni <a href="http://fr.wikipedia.org/wiki/Technophile" class="extern">technophile</a>, ni <a href="http://fr.wikipedia.org/wiki/Geek" class="extern">No life</a></li></ul> <h2>Quoi</h2> <p>Principalement du contenu lié directement à la <a href="http://www.adobe.com/flashplatform/" class="extern">plateforme flash</a>.<br/>Cependant <b>Flash</b> n'étant pas une prison fermée, j'espère partager sur tout autre aspect du <b>développement multimédia.</b><br/>Les billets de ce blog ne représentent pas la philosophie du développement au sein de l'agence SUPERSONIKS.</p> <h2>Comment</h2><br/> <div class="biglist"><ul><li>Il existe des outils de gestion de contenu reconnus (<b>Drupal, Wordpress, Joomla</b>..) <br/>Cependant je souhaitais aller voir un peu ailleurs.</li></ul> <ul><li>Ayant aimé jouer avec le <a href="http://haxe.org/doc" class="extern">méta-language Haxe</a>. <br/>j'ai souhaité qu'il soit à la base de ce blog, pour aller plus loin avec cet outil.<br/>il n'y a donc <b>pas une ligne de php</b> ici, mais ce langage <a href="http://haxe.org/doc/targets" class="extern">compilé vers js, flash et neko </a><br/>La partie serveur(neko) tourne à l'aide ce petit module apache <a href="http://nekovm.org/doc/mod_neko" class="extern">mod_neko</a></li></ul> <ul><li>Comme dit plus haut je ne suis pas un no life donc, je suis parti de cette <a href="https://svn.motion-twin.com/hxwiki/v2/" class="extern">base</a> intéressante<br/><em>(Le code est incomplet. il faut le modifier un peu, recréer la base à la main... pour commencer à le personnaliser un peu)</em></li></ul> <p>Je le répète ! Le but n'est pas de faire un blog de compète, mais de voir/essayer un peu autre chose.</p> </div>