10
I Use This!
Activity Not Available

News

Analyzed 2 days ago. based on code collected 2 days ago.
Posted over 16 years ago by [email protected] (eKameleon)
Hello :) un petit message pour vous parler un peu des nouveautés concernant mon implémentation d'un package ioc dans AndromedA basé sur une notation ECMAScript et s'inspirant de quelques frameworks bien connu comme Spring.NET ou Spring JAVA.... Je peux dire que j'ai bien avancé et à l'heure actuelle le framework
Posted over 16 years ago by eKameleon
Généralité Voici la suite des aventures concernant Flash Media Interactive Server 3 et l'utilisation de la méthode BitmapData.draw() pour capturer un flux vidéo et le transformer en image via le protocol RTMP et un serveur distant. Je vous ... [More] conseille, avant de lire la suite, de regarder la première partie de cette troublante saga : BitmapData.draw() and Video Capture - Security sandbox violation. Nous avions vu que l'utilisation d'un serveur RTMP avec le FlashPlayer nécessité un hack pour capturer une image provenant d'un flux streaming distant. Hors avec FMS3 et surtout le nouveau Flash Player 9.0.115.0 il faut repartir de 0 et revoir complètement nos méthodes. Je savais que le nouveau FlashPlayer avant évolué au niveau de ses niveaux de sécurité mais je ne m'attendais pas à devoir "faire avec" avec les applications tournant sur FMS3 ... Sécurité du FlashPlayer 9.0.115.0 et RTMP Revenons donc à la nature de notre nouveau problème. Si l'on souhaite utiliser la méthode BitmapData.draw() avec FMS3 il va falloir se pencher sur deux nouvelles méthodes côté serveur de la classe Client Server Side ActionScript : Client.videoSampleAccess et Client.audioSampleAccess En effet avec le FMS3 il n'est plus possible de passer au dessus de la sécurité du Flash Player sans affecter une permission au niveau du Client côté serveur. Dans Flash en testant rapidement l'exemple de mon premier article on tombe rapidement sur un message "Security sandbox violation". Par exemple dans un simple fichier "main.asc" on peut écrire le code maintenant écrire le code suivant : application.onConnect = function( client ) {     // fix Security sandbox violation : BitmapData.draw on RTMP source   client.videoSampleAccess = "/";   this.acceptConnection(client) ;   } En donnant une valeur "/" à la propriété videoSampleAccess de l'objet de type Client. L'utilisateur du client Flash pourra donc librement utiliser la méthode BitmapData.draw() sur tous les flux vidéo qu'il voudra. Maintenant si l'on souhaite sécuriser une application au niveau de la diffusion des vidéos ou de l'utilisation de SharedObjects, il faut utiliser les méthodes Client.readAccess et Client.writeAccess qui existent depuis Flash Media Server 2. application.onConnect = function( client ) {       client.readAccess = "public" ; client.writeAccess = "public" ;   // fix Security sandbox violation : BitmapData.draw on RTMP source   client.videoSampleAccess = "public";   this.acceptConnection(client) ;   } Dans ce cas là il faudra utiliser côté client un publication de la classe NetStream (play et publish) sur un flux : "public/NomDeMonFlux". Maintenant si vos applications tournent parfois sur des serveurs FMS2 et parfois sur des serveurs FMS3 il faut se méfier car la méthode videoSampleAccess n'existe pas dans FMS2, en cas de doute je vous conseille d'utiliser un try..catch autour de votre instruction pour éviter les conflits avec un serveur FMS2 ou antérieur. application.onConnect = function( client ) {     // fix Security sandbox violation : BitmapData.draw on RTMP source   try { client.videoSampleAccess = "/" ; } catch( e /*Error*/ ) { trace("Warning : The method videoSampleAccess don't exist : " e.toString() ) ; }   this.acceptConnection(client) ;   } Après quelques tests il est assez simple de voir qu'il faudra passer à chaque fois par cette fonctionnalité pour libérer le flux vidéo des clients de nos applications FMS. D'un côté il est vrai que cette sécurisation permet une meilleure fiabilités des applications de VOD (Video on Demand). Le vrai problème Un problème provisoire subsiste. En effet si je reprends un code simple pour illustrer dans Flash CS3 en AS2 la capture d'un flux vidéo dans un BitmapData je peux taper : import flash.display.BitmapData ;   var url:String = "rtmp://localhost/test_security_rtmp" ; // rtmp application uri   // The NetConnection instance.   var nc:NetConnection = new NetConnection() ; nc.onStatus = function( oInfo:Object ) { trace( "-> " oInfo.code " : " oInfo.description ) ; }   nc.connect( url ) ;   var streamID:String = "public/test_live" ;   // The NetStream to publish the Camera   var nsOut:NetStream = new NetStream( nc ) ; nsOut.attachVideo( Camera.get() ) ; nsOut.publish( streamID ) ;   // The NetStream instance to play the external Video live stream. var nsIn:NetStream = new NetStream( nc ) ; nsIn.play( streamID , -1) ;   // The video object in the movieclip with the name "container" var video:Video = container.video ; video.attachVideo( nsIn ) ;   // The BitmapData instance. var bmp:BitmapData = new BitmapData(container._width , container._height) ;   Key.addListener(this) ;   this.onKeyDown = function() {   bmp.draw(container) ;   var capture:MovieClip = createEmptyMovieClip("capture", 10) ; capture._x = container._x container._width 10 ; capture._y = container._y ;   capture.attachBitmap( bmp, 1 ) ;   } Avec le Flash Player 9.0.115.0 pas de problème tout fonctionne parfaitement. Mais avec un Flash Player 9.0.68.0 ou inférieur cela se corse... En effet le code au dessus ne marche pas ! Il faut donc utiliser le hack que j'explique dans mon article précédent : video.attachVideo( null ) ; bmp.draw(container) ; video.attachVideo( nsIn ) ; Le soucis est que si l'on utilise ce hack avec le FlashPlayer 9.0.115.0 la capture vidéo ne marche plus ! Nous sommes donc face à un petit soucis de compatibilité et de version du FlashPlayer, il faut donc pousser l'utilisateur pour qu'il mette à jour son player ? Avec un détection via SWFObject cela peut s'arranger mais c'est tout de même pas très pratique dans tous les cas de figure. Si l'utilisateur a déjà le FP9 mais qu'il n'a pas la dernière version il faut bien lui expliquer le problème etc... cela peut prendre un peu de temps pour l'utilisateur et lui faire perdre un peu le rythme dans l'utilisation de son applicatif. Pour ma part en attendant que le dernier FlashPlayer soit plus largement diffusé j'ai modifié un peu mon code et j'utilise une classe fort sympatique qui se trouve dans le package asgard.system de VEGAS mon framework opensource : import asgard.system.Version;   import flash.display.BitmapData ;   var s:String = System.capabilities.version ; var v:Version = Version.fromString( s.split("")[1] , ",") ;   var isFlashPlayer9_0_115:Boolean = (v.major >= 9) && (v.build >= 115) ;   var url:String = "rtmp://localhost/video" ; var url:String = "rtmp://213.189.19.240/video" ;   // The NetConnection instance. var nc:NetConnection = new NetConnection() ; nc.onStatus = function( oInfo:Object ) { trace( "-> " oInfo.code " : " oInfo.description ) ; }   nc.connect( url ) ;   var streamID:String = "public/test_live" ;   // The NetStream to publish the Camera var nsOut:NetStream = new NetStream( nc ) ; nsOut.attachVideo( Camera.get() ) ; nsOut.publish( streamID ) ;   // The NetStream instance to play the external Video live stream. var nsIn:NetStream = new NetStream( nc ) ; nsIn.play( streamID , -1) ;   // The video object in the movieclip with the name "container" var video:Video = container.video ; video.attachVideo( nsIn ) ;   // The BitmapData instance. var bmp:BitmapData = new BitmapData(container._width , container._height) ;   Key.addListener(this) ;   this.onKeyDown = function() {   if ( isFlashPlayer9_0_115 == false ) { video.attachVideo( null ) ; }   bmp.draw(container) ;   if ( isFlashPlayer9_0_115 == false ) { video.attachVideo( nsIn ) ; }   var capture:MovieClip = createEmptyMovieClip("capture", 10) ; capture._x = container._x container._width 10 ; capture._y = container._y ;   capture.attachBitmap( bmp, 1 ) ;   } La classe Version inspirée à l'époque par Zwetan dans un article sur le FCNG (coding session 05) me permets de manipuler facilement la version du FlashPlayer du client utilisé pour switcher le hack sur la diffusion du flux vidéo en créant une variable Booléenne isFlashPlayer9_0_115 qui permet de fixer le code. var s:String = System.capabilities.version ; var v:Version = Version.fromString( s.split("")[1] , ",") ;   var isFlashPlayer9_0_115:Boolean = (v.major >= 9) && (v.build >= 115) ; Conclusion C'est très bien que Adobe pousse la sécurité du FlashPlayer mais la transition est un peu brusque, la dernière version du Flash Player et de FMIS3 nous pousse à faire attention pour nos prochaines applications au niveau de la sécurité mais tout cela ne stabilise pas vraiment les applications en cours. Il faut à chaque fois les maintenir en transformant plus ou moins le code à chaque fois... C'est surtout mes clients qui n'apprécient pas trop que leurs applications ne fonctionnent plus. Le pire dans tout cela c'est la veille technologique qu'il faut effectuer à chaque fois lorsque Adobe met à jour FMS lol Il est vrai que la documentation sur la méthode videoSampleAccess existe mais les informations ne sont pas forcément plus clair après l'avoir lue. Il faut absolument faire des tests pour comprendre parfaitement les finesses de ces méthodes. Adobe doit vraiment encore faire des efforts à ce niveau là. Je me demande d'ailleurs ce qu'il en est de la sécurité du FlashPlayer 9.0.115.0 et des serveurs comme Wowza, Red5 ou encore HaxeVideo ? Il faudra que je teste tout cela pour voir si ces serveurs ont le même problème ou pas ? Remarque : vous pouvez retrouver cet article sur le Google Groups de mon blog . [Less]
Posted over 16 years ago by eKameleon
Généralités Voici mon premier feedback technique sur Flash Media Interactive Server 3.... Sérieux... pourquoi Adobe donne un nom aussi compliqué à son serveur ? A chaque fois que je suis obligé de parler de FMS3 j'ai l'impression de discuter de la ... [More] dernière version de Street Fighter 2 Turbo X fatal mega super tropdur alpha combo lol Donc je décide de faire simple et d'utiliser le terme FMS3 dans la suite de mes articles... (fin de cette petite note sur la nomenclature de mes articles traitant de FMS3 :D) Comme je l'ai déjà dit, les enjeux majeurs de cette nouvelle version de FMS reste une amélioration des performances, une amélioration de la qualité des vidéos en live streaming (full HD avec H264) et pour finir une baisse des prix des licences et une simplification de celles ci en proposant seulement 2 types de serveurs (oui quand je parle de simplification, je ne parle pas du nom des serveurs... cf début de ce message ;)) Reste que pour ma part, même si après l'annonce officielle de la sortie de FMS3 je n'avais que très peu d'espoirs dans les nouveautés au niveau du code côté serveur (pas d'AS3 ou d'ES4 côté serveur), j'espérais que Adobe mettrait un peu plus d'efforts dans l'évolution de la nouvelle version de FMS en faisant une petite mise à jour du moteur Javascript SSAS de FMS. J'avais de gros espoirs là dessus en prenant en compte l'arrivée de l'E4X en AS3 et de la disponibilité de l'E4X depuis la version 1.6 du Javascript. Surtout qu'en regardant Flash CS3 de plus prêt on se rend rapidement compte que le moteur JSFL est bien en version 1.6 ! Ainsi, pendant l'installation du serveur j'ai rapidement ouvert le PDF flashmediaserver_SSLR.pdf contenu dans le répertoire de documentation du serveur et tout de suite j'ai était "choqué" en lisant une documentation pratiquement similaire à la version que l'on peut trouver dans l'installation de FMS2 avec dès le début le joli paragraphe : Server-Side ActionScript is Adobe’s name for JavaScript 1.5. Flash Media Interactive Server has an embedded Java-Script engine that compiles and executes server-side scripts. This Server-Side ActionScript Language Reference documents the Flash Media Interactive Server host environment classes and functions. You can also use core Java-Script classes, functions, statements, and operators. For more information, see the Core JavaScript 1.5 Reference at http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference. For more information about JavaScript, see “About JavaScript” in the Mozilla Developer Center at http://developer.mozilla.org/en/docs/About_JavaScript. Bref... je veux bien que l'on ne passe pas tout de suite à une version Javascript 2 ou AS3/4 du SSAS mais là c'est vraiment n'importe quoi ! Il faut à mon avis très peu de temps pour changer le JS engine de FMS pour les développeurs d'Adobe et il ne faut pas oublier qu'à l'heure actuelle Mozilla est en train de diffuser les bases du Javascript 1.8... Politique commerciale ou tout simplement simple suffisance des développeurs d'Adobe. Pour ma part je me demande sérieusement si Adobe utilise sérieusement son serveur. Je passerai rapidement sinon sur la couche "script" des composants FMS mis à jour dans le répertoire scriptlib de l'installation du serveur avec un code tout juste remis à jour au niveau de la licence en entête des fichiers .asc. Au final, j'ai beau chercher et je ne vois que très peu de nouvelles méthodes dans la documentation du serveur et encore pire ! La nouvelle documentation ne donne aucune information sur la compatibilité des méthodes côté serveurs compatibles avec FMS2 ou FCS 1.5 Il faut maintenant que je me penche un peu plus sur la documentation du PLUG-IN DEVELOPER GUIDE mais pour le reste une simple relecture rapide suffira je pense. Alors oui ! C'est génial que le prix de la licence baisse ! C'est génial que la qualité des vidéos et la sécurité soient meilleures ! C'est génial d'avoir une version plus stable et performante du serveur ( peut être car à chaque fois que Adobe nous dit que le serveur est stable je me retrouve avec des soucis avec mes clients ... ) ! Mais sérieusement il y a un manque réel de suvi sur les besoins des développeurs SSAS. On est limite dans un flou artistique depuis le début avec FMS qui favorise l'utilisation des composants de Adobe (vraiment médiocres pour le moment) et commercialement annonce bien la sortie prochaine des projets Cocomo et Pacifica. AMF3 avec FMS3 J'en reviens maintenant au sujet de mon article, avec l'utilisation du protocol AMF3 avec FMS3 Bonne nouvelle malgré tout ce que j'ai pu dire plus haut, FMS3_ apporte la possibilité d'utiliser des données transférées entre le serveur et les clients Flash via le protocol AMF3. Il est donc possible maintenant de diffuser des ByteArray et des instances de type XML(E4X) directement via les méthode NetConnection.call() (AS3) et Client.call()__ (SSAS). Voici donc un petit exemple d'utilisation de l'AMF3 avec Flash CS3 et FMS3 : Voici une petite classe permettant de mettre en avant la diffusion via le serveur d'un objet custom : [actionscript]3 package test { import vegas.core.CoreObject ; public class UserVO extends CoreObject { public function UserVO( name:String=null ) { if ( name != null ) { this.name = name ; } } public var name:String ; public override function toString():String { return "[User " (name || "empty") "]" ; } } } Voyons maintenant le code côté Flash CS3 import flash.events.NetStatusEvent ; import flash.net.NetConnection ; import flash.net.registerClassAlias ; import flash.net.Responder ;   import test.UserVO ;   var rtmpUrl:String = "rtmp://localhost/test" ;   var u:UserVO = new UserVO( "eka" ) ;   registerClassAlias( "UserVO", UserVO ) ; // classmapping   var buffer:ByteArray ;   var netStatus:Function = function( e:NetStatusEvent ):void {   var info:Object = e.info ;   trace(info.code " : " info.description " : " info.level ) ;   buffer = new ByteArray(); buffer.writeObject(u);   nc.call( "test" , responder, buffer ) ;   nc.call( "test2" , responder ) ;   }   var result:Function = function( ...args:Array ):void { var buffer:* = args[0] ; var o:* = buffer.readObject(); trace("result : " o ) ; }     var status:Function = function( ...args:Array ):void { var error:* = args[0] ; trace("status : " error ) ; for ( var prop:String in error ) { trace(prop " : " error[prop] ) ; } }   var responder:Responder = new Responder( result , status ) ;   var nc:NetConnection = new NetConnection() ; nc.addEventListener( NetStatusEvent.NET_STATUS , netStatus ) ;   nc.connect( rtmpUrl ) ; J'utilise la classe ByteArray pour diffuser une copie de mon objet via le serveur FMS. Script côté serveur dans un fichier test/main.asc /** * This property register a ByteArray from the client and returns this value in the test2() method. */ var memory ;   /** * call from the client with the NetConnection.call method. */ Client.prototype.test = function( o ) { trace("test : " o ) ; // test : [object ByteArray] trace("length : " o.length ) ; // length : 19 trace("objectEncoding : " o.objectEncoding ) ; // undefined // trace("user ? : " o.readObject() ) ; // ## TypeError : o.readObject is not a function ## memory = o ; return o ; }   /** * call from the client with the NetConnection.call method. */ Client.prototype.test2 = function( o ) { return memory ; }     application.onAppStart = function () { trace("application start") ; }   application.onAppStop = function () { trace("application stop") ; }   application.onConnect = function ( client ) { trace("connect client : " client) ; application.acceptConnection( client ) ; }   application.onDisconnect = function( client ) { trace("disconnect client : " client) ; } Après avoir mi en place ces 3 bouts de code je lance la compilation dans flash et j'obtiens dans le panneau de sortie les messages suivants : geshi NetConnection.Connect.Success : Connection succeeded. : status result : [User eka] result : [User eka] Du côté de la console d'administration du serveur j'obtiens : geshi connect client : [object Client] test : [object ByteArray] length : 19 objectEncoding : undefined Analyse et conclusion J'arrive donc à envoyer un objet de type ByteArray (cela marche pareil pour un objet de type XML en E4X) vers le serveur et je peux le renvoyer également vers le client comme il faut. Je peux également stocker cet objet côté serveur et le renvoyer par la suite vers un Client (voir la variable memory et la méthode test2() dans le code SSAS). Le gros soucis... toujours par rapport à la version du Javascript 1.5 du SSAS c'est qu'il est impossible de manipuler simplement les objets côté serveur. En effet la classe ByteArray n'existe pas côté serveur et la classe XML n'est pas compatible E4X (idem que la version AS1/AS2). Il est peut être possible d'utiliser la classe File SSAS pour récupérer le byteArray et le stocker en fichier sur le serveur ? Faudra que je fasse des tests avec une image JPG envoyée directement vers le serveur ou un Zip... En attendant comme vous pouvez le voir dans l'exemple au dessus je récupère l'objet, sa propriété length mais c'est à peut prêt tout... Donc je ne peux pas utiliser la méthode readObject de la classe ByteArray pour reconstituer l'objet côté serveur. Je vais donc être obligé de continuer à utiliser le class mapping côté serveur avec la méthode application.registerClass() pour passer mes objets customs vers le serveur. Classmapping avec FMS3 Le classmapping dans FMS3 sera le même que dans FMS2 et FCS1.5 Je ne vais donc pas épiloguer là dessus plus longtemps, j'avais déjà parlé de ce problème dans mon article Undocumented SSAS/JS methods and VEGAS Server Side ActionScript. Il est donc impossible de faire du classmapping sur des fonctions constructeur (classes) déclarées avec une fonction anonyme ! C'était vraiment important pour moi que Adobe modifie la méthode application.registerClass() SSAS pour qu'elle fonctionne comme la classe Object.registerClass côté client mais vu que Adobe n'est pas vraiment ouvert quand on parle de Flash Media Server sur leurs News Groups ou forums... j'ai bien l'impression que sur ce coup là il faudra attendre FMS4 et un éventuel langage côté serveur basé sur AS4/ES4 (là faut vraiment qu'ils le fassent) pour avoir des corrections à ce niveau là. Entre les soucis de classmapping en AS3 (valeur des propriétés déserialisées attribuées après le constructeur en AS3) et les soucis côté serveur... Adobe oubli ici de maximiser un point fort de leur serveur de pouvoir transférer des données customs entre le serveur et le client le plus facilement du monde comme on pourrait le faire avec Flash Remoting et AMFPHP par exemple Conclusion Pas grand chose à dire niveau ServerSide ActionScript sur cette nouvelle version de FMS. L'apport de l'AMF3 va permettre quelques bonnes choses comme la diffusion simultanée d'un BitmapData via le serveur sans avoir à créer un jpeg sur un serveur web distant. Ou l'envoi direct d'un flux XML (stream ou pas ?) du client vers le serveur sans se prendre trop la tête.. Je verrai plus tard ce qu'il en est en utilisant la classe XMLSocket(Stream) côté serveur pour diffuser des flux vidéos ou son vers des serveur JABBERT ou autre (VOIP, etc..) mais en attendant pas de précipitation lol Une bonne chose par contre c'est que je vais pouvoir finaliser tranquillement la version SSAS de mon framework ECMAScript multi Flash plateforme : VEGAS VEGAS SSAS a encore quelques années de vie en l'état actuel et je vais d'ici quelques mois le faire évoluer une bonne fois pour toute pour utiliser tous les outils IOC disponibles à l'heure actuelle dans la version AS3 de VEGAS et qui vont me faire gagner à terme beaucoup de temps pour créer mes applications serveur avec FMS3... Cela me fait penser que je ferais bien de faire un petit tutoriel pour expliquer comment cabler mon framework dans une application FMS Je rappel pour les plus curieux d'entre vous que j'ai commencé à mettre en place des tutoriaux dans mon autre Framework documentaire : AST'r qui exploite les possibilités de VEGAS SSAS (MVC, FrontController, Event model W3C etc...), voir le SVN du projet et l'exemple en cours de construction qui se trouve dans le répertoire : /trunk/AS2/trunk/examples/echat Comme toujours si vous avez des questions ou des remarques sur le sujet, vous pouvez poster un petit commentaire ou m'envoyer des messages sur les 2 Google Groups disponibles : Google Groups VEGAS SOS : Pour vos question à propos de VEGAS Google Groups eKameleon : Pour vos remarques et questions au sujet des articles sur mon blog A venir des articles et des retours sur la stabilité du serveur, ses performances, ces nouvelles fonctionnalités avec le mode Flash Media Stream Server 3, etc... [Less]
Posted over 16 years ago by eKameleon
Généralité C'est tout chaud, avec une annonce de Zwetan ce matin sur le FCNG. Nous savions que FMS3 devait sortir en cette fin de mois de janvier mais comme toujours, avec la politique de communication de Adobe, la date de sortie restait très ... [More] floue. C'est donc aujourd'hui que nous pouvons télécharger officiellement FMIS3 et FMSS3 sur le site de Adobe : http://www.adobe.com/products/flashmediaserver/ Donc en gros Adobe nous propose 3 versions de FMS... mais au final c'est toujours la même chose (ou presque) Flash Media Interactive Server 3 (FMIS3) C'est la version complète du serveur. Avec la possibilité d'utiliser des scripts côté serveur (SSAS) pour créer des applications de streaming et multiutilisateurs. Flash Media Streaming Server 3 ( FMSS3 ) Permet de créer un serveur de VOD simplement (à première vue avec un fichier application.xml) et de diffuser de la vidéo simplement. Je n'ai pas encore testé tout cela, mais je reviendrai vers vous dès que j'en saurai plus. Flash Media Development Server (FMDS3) Pareil que le FMIS3 mais limité à 10 utilisateurs (pas de changement donc là dessus) Les nouveautés Multi-way applications Unlimited scalability with Origin/Edge Plug-in architecture for LDAP authentication C plug-in architecture Multipoint publishing Server redirection AMF3 support Server side playlists Video recording Pour ma part c'est surtout le support de l'AMF3 et la possibilité de créer des plug-in en C qui m'intéresse. Pour ce qui est du "Server redirection", il va falloir voir si cela passe comme il faut surtout pour VISTA (voir problème de filtrage TCP/IP sous VISTA) Sinon j'ai cru voir que l'option "Video recording" va permettre d'enregistrer directement les vidéos sur DVD ? Là encore un peu flou sans avoir testé la fonctionnalité. On pourra noter sinon dans le répertoire d'installation du serveur pratiquement aucun changement par rapport aux autres version de Flash Communication Server ou Flash Media Server 2. Tout juste dans le répertoire modules\streams un fichier libmp4.dll qui nous dévoile la possibilité d'utiliser des fichier au format mp4 pour lire des vidéos HD. Il faudra également prendre un peu de temps pour apprendre à utiliser dans le répertoire tools\ les nouvelles applications en ligne de commande fmscheck.exe et flvcheck.exe. Au niveau des exemples et de la documentation là aussi il y a du changement... avec des exemples AS3 (exclusivement pour Flash CS3) et quelques exemples AS2. Mais en regardant bien... le code source des composants FMS côté serveur n'a pas bougé d'un pouce... (à part l'entête de la licence Adobe lol). On sent bien que Adobe attend la sortie de Cocomo et Pacifica pour nous sortir des outils en MXML et avec un code un peu plus propre à mon avis. Conclusion rapide J'ai rapidement installé le serveur et mes premières impressions sont très mitigées... Entre la console d'administration qui n'a pas changé d'un pouce et le Javascript qui reste en version 1.5... je me dis que sérieusement Adobe fait comme toujours au niveau de FMS son minimum pour satisfaire les développeurs qui utilisent son serveur depuis quelques années maintenant. Le nouveau serveur est orienté "video et sécurité" et surtout pas développeur. J'ai regardé un peu la documentation SSAS fournie dans le pdf flashmediaserver_SSLR.pdf et les nouveautés sont minimes ! Je ne trouve pas d'ailleurs d'infos sur le classmapping avec AMF3 et l'utilisation des ByteArray ? La documentation de FMS reste donc superficielle et sans saveur pour un développeur qui cherche à aller un peu plus loin et surtout qui ne cherche pas à utiliser les composants proposés par Adobe ! Au final, cela fait que 2 heures que j'ai télécharger le nouveau serveur et il va me falloir 1 ou 2 semaines pour faire un point et prendre du recul sur cette nouvelle version. Je reviendrais donc vers vous à ce moment là pour vous donner mes impressions avec un peu plus de lucidité. [Less]
Posted over 16 years ago by eKameleon
Présentation du problème Voici un petit article rapide pour vous informer d'un gros problème que j'ai pu rencontrer ces dernières semaine lors de la mise en ligne de plusieurs projets basés sur des applications qui se connectent à un serveur Flash ... [More] Media Server. Pour une fois, je ne peux pas mettre en cause la stabilité du serveur FMS car au final c'est bien Windows VISTA qui n'aime pas Flash Media Serveur La description du problème reste simple et se résume au ralentissement des échanges de données entre un client Flash et un serveurt FMS. Par exemple pour connecter un client Flash avec un serveur FMS en ligne, la connexion entre le client et le serveur se fait bien automatiquement mais ensuite les informations ou données renvoyées par le serveur peuvent prendre en moyenne 3 à 5 secondes pour revenir à chaque requête vers le client Il m'a fallu un certain temps pour trouver la nature exacte du problème. En prenant tout d'abord en compte la possibilité que le bug puisse provenir du Flash Player lui même (problème de stabilité du player avec Windows VISTA ?). Mais non le problème ne provient pas du FlashPlayer. Il faut dire qu'avec toutes les sécurités injectées dans les dernières version du player, j'ai eu très peur que Adobe nous ai coulé FMS en sortant les dernières version du FlashPlayer mais ce n'est pas le cas. J'ai également très vite repoussé l'idée d'un bug provenant de mon code car l'application fonctionne parfaitement sur les autres versions de Windows, ainsi que sur MAC. Il reste donc que Windows Vista dans la liste des responsables ! N'ayant pas Windows Vista installé sur ma machine, il a fallu tout d'abord que je me procure un ordinateur tournant sous une configuration VISTA et ensuite il a fallu passer beaucoup de temps dans les pages de Google pour trouver une réponse à mon problème. Je remercie au passage Zwetan pour quelques liens envoyés un soir sur Google Talk qui m'ont permis au final de trouver la solution... enfin si on peut appeler cela une solution lol Il est clair que la sécurité de VISTA pose problème et que le problème d'échange de données entre un client Flash et un serveur FMS n'est pas le seul problème rencontré sur la toile avec cet OS. Donc, en cherchant un peu en profondeur on se rend compte que le gros soucis vient d'une protection sur les données réceptionnées par VISTA avec le protocol TCP/IP. Travaillant pour ma part sur un Window XP pro je n'avais pas imaginé qu'un tel problème puisse exister et je peux vous dire qu'après de longs mois de développement sur une application, c'est assez décourageant de se rendre compte qu'un problème comme celui là (indépendant de notre volonté) peut compromettre des heures et des heures de travail. En effet... Vista est diffusé massivement dans toutes les configurations actuellement en vente (portable ou ordinateur acheté en magasin) et un utilisateur lambda n'a pas le réflex d'acheter une machine sans VISTA. Solution actuelle au problème Voici tout d'abord le lien qui m'a permis de trouver une réponse à ce problème : Slow network in Vista? Windows Vista propose une protection des données reçues en TCP/IP avec un filtrage activé par défaut, chez Microsoft ils appellent cela le Receive Window Auto-Tuning Level Pour configurer et éditer cette protection dans VISTA il faut suivre les opérations suivantes : Touche VISTA Ouvrir la console DOS en tapant : CMD Taper ensuite dans la console la commande : netsh interface tcp show global Il s'affiche alors les paramètres de sécurité TCP de VISTA : TCP Global Parameters ------------------------ Receive-Side Scaling State : enabled Chimney Offload State : enabled Receive Window Auto-Tuning Level : enabled Add-On Congestion Control Provider : none ECN Capability : disabled RFC 1323 Timestamps : disabled Nous pouvons nous rendre compte que la protection est bien activée par défaut avec la ligne : Receive Window Auto-Tuning Level : enabled Procédure pour désactiver la sécurité TCP de VISTA Il faut donc désactiver cette protection. Je peux dire que pour réaliser cette opération à la main, il va être difficile de demander à un utilisateur lambda de réaliser cette opération... Il faut donc ouvrir la console de commande en mode "administration" : Touche VISTA. Taper CMD dans le moteur de recherche en dessous de tous les programmes. Taper CTRL SHIFT ENTER en gardant le focus dans la barre de recherche. Appuyer sur ALT C pour lancer la console d'administration. Taper dans la console d'admin la commande : netsh interface tcp set global autotuning=disabled Une fois cette opération correctement effectuée, nous pouvons relancer notre application et la connexion se fait automatiquement à vitesse normale et ensuite les transferts de données entre le serveur et le client se font à la vitesse habituelle (tout dépend du serveur et de ses capacités bien entendu). Remarque : pour réactiver la protection il faut utiliser la commande inverse netsh interface tcp set global autotuning=normal Conclusion En cherchant un peu plus loin les discussions sur le sujet de cette protection, il faut attendre à première vue la version SP1 de VISTA pour espérer une correction de ce problème (mais difficile d'être certain d'une telle correction vu que pour le moment le contenu du SP1 n'est pas encore bien clair pour moi). Sinon concrètement à l'heure actuelle il faut proposer à l'utilisateur une solution automatisée pour désactiver la protection de VISTA et je peux comprendre qu'un utilisateur peu averti peu trouver "dérangeant" de devoir lancer une application (.bat ou .exe ou autre application standalone) pour désactiver une sécurité sur sa machine... Il faut donc communiquer largement au niveau du client pour expliquer cette problématique aux utilisateurs sous VISTA et cela prend du temps et de l'énergie Sur le coup et la fatigue aidant (pendant la recherche d'une solution) je peux avouer que j'ai presque pensé que Microsoft a créé ce filtrage pour mettre en avant SilverLight et brider FMS et les technologies Adobe. Mais en fait il ne faut pas voir le mal partout il parait Sachant que j'imagine très bien que ce problème puisse être le même pour des applications utilisant du serveur XMLSocket ou autre. Au final, j'espère sérieusement que Adobe prend en compte avec la sortie prochaine de Flash Media Server 3 ce problème et fait tout son possible pour contourner ce problème (par une mise à jour du player ou par une discussion active avec les développeurs de la SP1 de Windows ?) [Less]
Posted over 16 years ago by eKameleon
Généralité La classe AS2 asgard.display.DisplayObject est une classe très importante car elle permet de créer des objets qui permettent de contrôler les vues d'une application. Les vues d'une application en ActionScript 2 c'est avant tout des clips ... [More] (MovieClip), des champs de texte (TextField) et des vidéos. La classe DisplayObject permet d'étendre les possibilités des objets visuels dans vos applications en utilisant le principe de composition. La composition est un principe en programmation important qui permet de relier 2 objets ensembles et il est vrai que dans les concepts plus ou moins avancés de programmation orienté objet il existe plusieurs "écoles" entre ceux qui utilisent la composition ou ceux qui au contraire vont prévilégier l'utilisation d'une délégation entre les objets par héritage. Voyons avant d'aller plus loin 2 petits exemples pour illustrer les 2 notions de composition et d'héritage pour créer une classe qui va étendre les possibilités de la classe MovieClip : Héritage class CustomDisplay extends MovieClip {   function CustomDisplay() {     }   // ....   } Composition class CustomDisplay {   function CustomDisplay( target:MovieClip ) { view = target ; }   public var view:MovieClip ;   // ....   } Dans le cas de la composition l'exemple ci-dessus met en avant la déclaration d'une propriété qui servira de référence vers l'objet visuel dont dépend la classe et qui étendra du coup ses possibilités. En AS1 et AS2 nous avions par exemple le classes Color et Sound qui utilisent cette technique. Différence entre AS2 et AS3 En AS2 après de longues années à utiliser l'héritage j'ai décidé d'équilibrer un peu les choses en gérant les vues principales de mes applications en utilisant une classe très proche (polymorphisme) de la classe AS3 du même nom tout en gardant à l'esprit que en AS2 l'architecture et le moteur graphique n'est pas le même qu'en AS3. En effet alors qu'en AS1 et AS2 les classes MovieClip, TextField et Video héritent directement de la classe Object (la classe de plus bas niveau dans les langages basés ECMAScript 262 édition 3), en AS3 la classe MovieClip possède un héritage beaucoup plus riche que je vous invite à observer sur le schéma qui se trouve dans la documentation AS3 de Flash CS3 : Classes d'affichage de base en AS3 On peut observer qu'en dessous de toutes les classes visuelles AS3 du package flash.display on trouve en premier niveau d'héritage la classe flash.events.EventDispatcher. Aussi VEGAS proposant un modèle évènementiel proche de celui disponible dans le framework AS3, j'ai décidé de reconstituer dans l'absolu un schéma d'héritage de mes classes visuelles dans VEGAS basé sur un modèle AS2 proche du modèle AS3 même si il est vrai que très rapidement les limites de l'AS2 ferment des portes et qu'il est préférable pour avoir quelquechose de complètement "clean" de passer à l'AS3 et de plus revenir en arrière ensuite Maintenant vu le nombre de projets AS2 que j'ai encore à faire pour finir cette année 2007 et qui chevaucheront surement encore un peu les premiers mois de 2008... la classe asgard.display.DisplayObject reste d'actualité ! Description et utilisation de la classe DisplayObject Utilisation de base Il existe une multitude de manière pour utiliser la classe DisplayObject. La plus simple reste de l'instancier tout simplement comme ceci : import asgard.display.DisplayObject ;   var target:MovieClip = createEmptyMovieClip("mcTarget", 1) ;   var display:DisplayObject = new DisplayObject( "myDisplay", target) ;   trace(display) ; // [DisplayObject] Le premier argument du constructeur correspond au nom que l'on souhaite donner à notre DisplayObject et le second argument correspond à la référence de l'objet visuel que l'on veut contrôler. Le premier argument est facultatif et permet d'alimenter la propriété virtuelle name du display. La grosse particularité de cette propriété c'est qu'il ne peut pas y avoir 2 displays portant le même nom dans toute votre application. Le but de cette propriété name n'est pas de remplacer la propriété _name du clip par exemple, mais sert en fait d'identifiant unique pour l'objet pour le retrouver facilement dans vos applications via une classe statique qui se nomme DisplayObjectCollector ( Nous verrons un peu plus loin l'utilisation de cette classe ). De façon général j'utilise beaucoup les DisplayObject pour contrôler des MovieClip mais il est possible de passer en second paramètre du constructeur de la classe DisplayObject toute sorte d'objet (Video, TextField, MovieClip...) Vu que la classe DisplayObject utilise la composition pour ajouter des fonctionnalités à un objet visuel, pour retrouver la référence de cet objet il suffit d'utiliser la propriété view de la classe : import asgard.display.DisplayObject ;   var mc:MovieClip = createEmptyMovieClip("myMovieClip", 1) ;   var display = new DisplayObject( "myDisplay", mc ) ;   trace( "display : " display) ; // display : [DisplayObject] trace( "view : " display.view ) ; // view : _level0.myMovieClip trace( "name : " display.name ) ; // name : myDisplay Le constructeur de la classe DisplayObject peut émettre une erreur de type vegas.errors.IllegalArgumentError si le constructeur n'arrive pas au moment de créer l'instance à déterminer concrètement une vue à contrôler. import asgard.display.DisplayObject ;   try { var display = new DisplayObject( "myDisplay" ) ; } catch( e:vegas.errors.IllegalArgumentError ) { trace(e) ; // [IllegalArgumentError] invalid arguments for [DisplayObject] constructor. } Dans l'exemple ci-dessus aucun objet visuel est passé en référence en second paramètre de la fonction constructeur du display. Les propriétés de la classe DisplayObject Nous avons vu la propriété view mais en plus de cette propriété, la classe DisplayObject profite de sa composition et de son polymorphisme avec la classe de Adobe AS3 en simplifiant un peu certaines propriétés comme : alpha : Une valeur entre 0 et 100 qui permet de modifier le niveau de transparence de la vue du display. enabled : Permet d'activer ou désactiver l'activité de type "button" de la vue du display. height : Renvoi et modifie la hauteur du display. mouseX : position de la souris en x dans le référentiel de la vue du display. mouseY : position de la souris en y dans le référentiel de la vue du display. name : nom "unique" du display dans l'application qui permet de retrouver sa référence facilement via une classe statique singleton DisplayObjectCollector. root : renvoi un DisplayObject qui contrôle la sc_ne principale (Attention ce DisplayObject a une propriété name qui a pour valeur "root"). rotation : permet de modifier l'angle de rotation de l'objet visuel que le DisplayObject contrôle. tabEnabled : Permet d'activer ou de désactiver le display dans l'ordre de tabulation auquel il appartient dans l'application. tabIndex : Permet de modifier l'ordre de tabulation du display. x : permet de modifier la position en x du display dans son référenciel. xScale : permet de modifier le ratio en largeur du display. y : permet de modifier la position en x du display dans son référenciel. yScale : permet de modifier le ratio en hauteur du display. visible : permet de définir si le display est visible ou non (Boolean) width : Renvoi et modifie la hauteur du display. Toutes ces propriétés sont des propriétés virtuelles et possèdent un duo de méthode getter/setter pour les définir plus rapidement dans un code optimisé et nécessitant des manipulations importantes sur les displays. Les méthodes de la classe DisplayObject La méthode attachChild() La méthode attachChild utilise en interne la méthode statique attachChild de la classe vegas.util.factory.DisplayFactory pour attacher dynamiquement dans la vue contrôlée par le display un clip lié à l'animation dans la bibliothèque de votre swf avec un identifiant de liaison. Cette méthode fonctionne comme la méthode MovieClip.attachMovie à la seule différence qu'elle permet de passer en premier paramètre de la fonction une fonction constructeur (classe) qui hérite de la classe MovieClip et ainsi de modifier dynamiquement l'héritage de l'instance. Voyons un petit exemple qui illustre la méthode attachChild avec l'utilisation avec la classe lunas.display.components.button.SimpleButton qui permet de créer rapidement un petit smartClip. La classe SimpleButton est une classe qui hérite (indirectement) de la classe MovieClip et qui permet de donner d'étendre les fonctionnalités avancées de bouton d'un clip en élargissant les méthodes, propriétés et événements de celui ci. Il faut que le clip possède en interne 4 images clés ayant pour nom d'étiquette : disabled : état visuel lorsque le bouton est désactivé. down : état visuel lorsque l'utilisateur clique sur le bouton. over : état visuel lorsque l'utilisateur passe la souris sur le bouton. up : état visuel de base du bouton (souvant la première image clé. Remarque : La méthode stop() du clip est invoquée au lancement de celui ci. Mais je vous conseille de placer un stop() sur la première image clé du clip pour éviter tout soucis. Exemple d'utilisation : import asgard.display.DisplayObject ; import lunas.display.components.button.SimpleButton ; import pegas.events.ButtonEvent ; import vegas.events.Delegate ;   function debug( e:ButtonEvent ):Void { trace( e ) ; }   var display:DisplayObject = new DisplayObject("application", this) ;   var bt:SimpleButton = display.attachChild( SimpleButton, "buttonID" , "mcButton", 1 ) ; bt.addGlobalEventListener(new Delegate(this, debug)) ; bt.x = 25 ; bt.y = 25 ; bt.toggle = true ; Vous pouvez retrouver les sources de cet exemple sur le repository SVN de VEGAS AS2 : AS2/trunk/bin/test/lunas/display/components/button/SimpleButton.fla Je vous conseille vivement de faire un tour dans le code source de la classe AS2 DisplayFactory pour en savoir plus à ce sujet. La méthode createChild() La méthode createChild utilise en interne la méthode statique createChild de la classe vegas.util.factory.DisplayFactory pour créer dynamiquement dans la vue contrôlée par le display un clip . Cette méthode est beaucoup plus complète que la méthode attachChild car elle permet : 1 - De créer dynamiquement un nouveau clip vide comme on pourrait le faire avec la méthode MovieClip.createEmptyMovieClip : Pour cela il suffit de passer une valeur null dans le premier argument de la méthode. import asgard.display.DisplayObject ;   var display:DisplayObject = new DisplayObject("application", this) ;   var init:Object = { _x : 25 , _y : 25 } ; var myMovieClip:MovieClip = display.createChild(null, "myMovieClip", 1, this, init ) ;   trace( myMovieClip ) ; // _level0.myMovieClip Le dernier argument optionnel de la méthode (init) permet d'initialiser comme dans la méthode MovieClip.attachMovie la nouvelle instance créé. Voir sources de l'exemple sur le SVN : DisplayObject - createChild(null).fla 2 - D'attacher dynamiquement un clip dans le référentiel de la vue du display comme le ferais la méthode MovieClip.attachMovie : import asgard.display.DisplayObject ;   var display:DisplayObject = new DisplayObject("application", this) ;   var init:Object = { _x : 25 , _y : 25 } ; var myMovieClip:MovieClip = display.createChild( "view" , "myMovieClip", 1, this, init ) ;   trace( myMovieClip ) ; // _level0.myMovieClip Dans l'exemple ci dessus le premier paramètre "view" de la méthode correspond au nom de liaison du symbole de type MovieClip attaché dans la bibliothèque du fla de l'animation. Voir sources de l'exemple sur le SVN : DisplayObject - createChild( id ).fla 3 - De créer dynamiquement un nouveau clip vide qui sera instance d'une classe qui hérite de MovieClip : Exemple avec la classe lunas.display.components.button.EasyButton qui comme la classe SimpleButton précédente hérite dans LunAS de la classe MovieClip mais qui utilise cette fois ci une vue totalement générée dynamiquement : import asgard.display.DisplayObject ; import lunas.display.components.button.EasyButton ; import pegas.events.ButtonEvent ; import vegas.events.Delegate ;   function debug( e:ButtonEvent ):Void { trace( e ) ; }   var display:DisplayObject = new DisplayObject("application", this) ;   var init:Object = { _x : 25 , _y : 25 } ; var bt:MovieClip = display.createChild(EasyButton, "mc", 1, this, init ) ; bt.addGlobalEventListener(new Delegate(this, debug)) ; bt.label = "Hello World" ; bt.toggle = true ; J'ai donc dans l'exemple ci-dessus créé un clip vide (avec la méthode MovieClip.createEmptyMovieClip) et la méthode createChild() se charge ensuite de modifier le chemin du prototype de l'instance. Il est donc facile d'insérer dans les displays des clips "prototypement modifié" 4 - De créer dynamiquement un nouveau champ de texte dynamique vide qui sera instance d'une classe personnalisée qui hérite de TextField: Par exemple je peux créer une classe test.CustomTextField qui hérite de la classe TextField comme ceci : class test.CustomTextField extends TextField {   public function CustomTextField() {   setNewTextFormat( new TextFormat("arial", 11) ) ;   background = true ; backgroundColor = 0xFFFFFF ; selectable = false ; text = "my text" ; textColor = 0xFF0000 ;   _width = 100 ; _height = 20 ;   }   } Et ensuite il suffit d'utiliser la méthode createChild pour créer dynamiquement dans le display un nouveau champ de texte dynamique qui hérite de la classe test.CustomTextField : import asgard.display.DisplayObject ;   import test.CustomTextField ;   var display:DisplayObject = new DisplayObject("application", this) ;   var init:Object = { _x : 25 , _y : 25 } ; var myField:CustomTextField = display.createChild( CustomTextField , "myField", 1, this, init ) ;   trace( myField ) ; // _level0.myField Voir sources de l'exemple sur le SVN : DisplayObject - createChild( TextField ).fla isVisible(), hide() et show() Ces méthodes sont simple à utiliser et sont utilisées en interne de la propriété visible virtuelle (r/w). Elles permettent tout simplement de cacher et d'afficher la vue du display. release() Cette méthode permet de vider le contenu du display (supprimer la vue contrôlée par le display et vider en mémoire tous ce qui doit l'être) avant de supprimer complètement le display. En effet un DisplayObject manipule par composition une référence visuelle dans vos applications mais si la référence du display est totalement détruite il n'en sera pas forcément de même de la vue qu'elle contrôle. Pour des classes personnalisées qui héritent de la classe DisplayObject il sera intéressant d'overrider (surcharger) cette méthode pour la compléter en cas de besoin. Les méthodes resolve() et resolveVisual() Les méthodes resolve() et resolveVisual() sont des méthodes très pratiques dans un DisplayObject car elles permettent en premier lieu de s'assurer que la vue du display contient bien la référence d'un clip ou de tout objet visuel que l'on souhaite manipuler. En principe l'intérêt des DisplayObject c'est qu'ils permettent au runtime de "donner vie" aux vues d'une application mais si l'on souhaite par exemple prendre la main sur un clip placé sur la scène principale de l'animation et l'encapsulée avec une classe de type DisplayObject pour étendre ses fonctionnalités il faudra être certain que si cette vue contient bien les occurrences de type MovieClip, Video ou TextField que l'on souhaite ensuite contrôler. Voyons un petit exemple avec un petit fla qui contient sur sa scène principale un clip qui porte le nom d'occurence "window" et à l'intérieur de ce clip nous trouvons un sous clip qui a pour nom d'occurence 'button'. import asgard.display.DisplayObject ;   var main:DisplayObject = new DisplayObject("main", this) ;   var window:DisplayObject = new DisplayObject("window" , main.resolve("window" ) ) ;   // search and return the instance with the name 'button' in the view of the 'window' display object. var button:MovieClip = window.resolve("button") ; button.onPress = function() { trace(this " press") ; } La méthode resolve() permet de trouver dans la vue du display la référence que l'on souhaite. Si cette référence n'existe pas ou si nous avons par exemple mal orthographié son nom dans le panneau de propriété la méthode va renvoyer une erreur de type vegas.errors.Warning. Je reprends l'exemple ci-dessus en me trompant sur le nom d'occurence du clip (j'ajoute un 's' à la fin de son nom) : import asgard.display.DisplayObject ;   var main:DisplayObject = new DisplayObject("main", this) ;   try { var window:DisplayObject = new DisplayObject("window" , main.resolve("windows" ) ) ; } catch( e:vegas.errors.Warning ) { trace(e) ; // [Warning] [DisplayObject] resolve failed with the view : 'windows' } Cette méthode permet donc de s'assurer que le clip "window" sur la scène possède bien une propriété "button" et va interrompre le code en cas de problème. La méthode resolve() possède une autre faculté, la faculté de modifié lorsque elle est invoquée de modifier la profondeur de la cible visuelle que l'on cherche dans la vue du display. import asgard.display.DisplayObject ;   var main:DisplayObject = new DisplayObject("main", this) ;   var window:DisplayObject = new DisplayObject("window" , main.resolve("window" , 100) ) ; Dans l'exemple précédent le clip "window" était posé directement sur la scène et avait donc une profondeur négative. En utilisant la méthode resolve avec un second argument de type Number, j'ai modifié la profondeur du clip en le plaçant maintenant à la profondeur 100 sur la scène principale. Remarque : La fonction resolve permet de modifier la prodondeur des MovieClip mais aussi des TextField et des objets de type Video se trouvant dans la vue de votre DisplayObject. En effet par défaut en AS1 et AS2 il n'est pas possible directement de modifier la profondeur des Video et TextField. Seule la classe MovieClip possède une méthode swapDepths qui permet de modifier la profondeur des clips. Hors en triturant un peu le code et en utilisant correctement les méthodes (call et apply) de la fonction swapDepths contenue dans le prototype de la classe MovieClip nous pouvons nous rendre compte que l'on peut appliquer cette méthode sur les objets Video et TextField : MovieClip.prototype.swapDepths.call( myVideo , 100 ) ; MovieClip.prototype.swapDepths.call( myTextField , 200 ) ; J'ai intégré ce hack dans ma classe vegas.util.factory.DisplayFactory avec les méthodes statiques getDepth() et swapDepths() et j'utilise tout cela dans la méthode resolve de la classe DisplayObject. Je vais rapidement faire un point sur la méthode resolveVisual de la classe DisplayObject car elle fonctionne comme la méthode resolve() sauf qu'elle permet en plus de définir un nouveau héritage pour l'instance si elle existe. Je reprends l'exercice précédent en modifiant l'héritage du bouton et en lui attribuant la classe lunas.display.components.button.SimpleButton que nous avons vu précédemment : import asgard.display.DisplayObject ; import lunas.display.components.button.SimpleButton ;   import pegas.events.ButtonEvent ; import vegas.events.Delegate ;   var debug:Function = function( e:ButtonEvent ):Void { trace(e) ; }   var main:DisplayObject = new DisplayObject("main", this) ;   var window:DisplayObject = new DisplayObject("window" , main.resolve("window" , 100) ) ;   // search and return the instance with the name 'button' in the view of the 'window' display object. var button:SimpleButton = window.resolveVisual(SimpleButton, "button", 10) ; button.addEventListener( ButtonEvent.CLICK, new Delegate(this, debug) ) ; Voir sources sur des exemples dans le répertoire du SVN : /AS2/trunk/bin/test/asgard/display La classe asgard.display.DisplayObjectCollector En vous parlant un peu plus haut de la propriété name de la classe DisplayObject, j'ai introduit la notion d'un identifiant unique pour tous les DisplayObject de vos applications. La propriété name des displays est en rapport direct avec la classe DisplayObjectCollector. La classe DisplayObjectCollector est un singleton statique (pas besoin de l'instancier) qui sert de helper dans vos applications pour retrouver rapidement et globalement tous les displays principaux de celle-ci. Cette classe est basée principalement sur une Map(clé/valeur) qui permet de stocker toutes les références de vos DisplayObjects en fonction de leur nom unique. Toute la finesse de cette implémentation réside dans le code de la propriété virtuelle name qui automatise l'insertion de vos displays dans le DisplayObjectCollector. Il vous est donc possible d'utiliser le DisplayObjectCollector directement pour y insérer des displays mais vous pouvez profiter du premier paramètre du constructeur de la classe DisplayObject pour le remplir. La meilleure méthode étant de définir une énumération statique dans vos applications qui contiendra l'ensemble des noms (clés) de vos displays principaux. Voyons un exemple d'utilisation simple : import asgard.display.DisplayObject ; import asgard.display.DisplayObjectCollector ;   // Create a simple static enumeration list of all your displays in the application. var UIList = {} ; UIList.CANVAS = "canvas" ;   var display:DisplayObject = new DisplayObject( UIList.CANVAS, this.createEmptyMovieClip("mcDisplay", 1) ) ;   var canvas:DisplayObject = DisplayObjectCollector.get(UIList.CANVAS) ;   trace("canvas : " canvas) ; // canvas : [DisplayObject] // canvas name : 'canvas' trace("DisplayObjectCollector contains 'canvas' name : " DisplayObjectCollector.contains( UIList.CANVAS ) ) ; // DisplayObjectCollector contains 'canvas' name : true trace("DisplayObjectCollector contains canvas reference : " DisplayObjectCollector.containsDisplay(canvas)) ; // DisplayObjectCollector contains canvas reference : true Il est maintenant possible d'utiliser le DisplayObjectCollector pour retrouver à tout moment vos displays quelque soit l'endroit dans votre code. Conclusion Comme vous pouvez le voir, ce premier tutoriel sur les DisplayObject est déjà riche en informations. Il me reste encore pas mal de choses à vous expliquer sur le sujet et je pense qu'un second tutoriel ne sera pas de trop. Je vous invite en lisant ce tutoriel à utiliser les exemples sous forme de FLA que vous pourrez trouver sur le repository de VEGAS dans le répertoire /AS2/trunk/bin/test/asgard/display Comme d'habitude pour toutes vos questions vous pouvez poster un message sur le Google Group de VEGAS. Pour ceux qui débutent avec VEGAS je vous conseille de lire le tutoriel sur l'installation des sources du framework. Le prochain tutoriel finira cette explication des DisplayObject AS2 de ASGard en mettant en avant : La classe asgard.display.DisplayLoader L'intérêt de créer vos propres classes qui hériteront de la classe DisplayObject. L'utilisation de la classe ConfigurableDisplayObject. L'utilisation de la classe BackgroundDisplayObject. L'utilisation de la classe Bitmap (classe polymorphique avec la classe AS3 flash.display.Bitmap mais basée sur la version AS2 des DisplayObject) [Less]
Posted over 16 years ago by eKameleon
Voici un petit message qui sort un peu de ma ligne éditoriale habituelle avec une proposition d'offre d'emploi pour la société JobinLive spécialisée dans le vidéo recrutement dans le sud de la france (Marseille). En plus de travailler au soleil et ... [More] prêt de la mer (super important pour le moral et la motivation ;)), le candidat sélectionné travaillera directement avec une équipe de développeur (dont je fais parti en tant que chef de projet et responsable R&D) sur de nombreux projets online et offline utilisant principalement des technologies comme Flash Media Server, Flash Remoting, AIR, etc. Il n'y a pas de profil particulier sur le plan de l'éducation. Un portfolio avec des références ou projets prouvant les talents du candidat sera aussi important que des années d'étude. Le candidat devra tout de même justifier une certaine expérience dans le profil recherché. Poste proposé : WebDesigner et développeur ActionScript avec bonne maitrise dans le domaine du montage vidéo et de l'animation. Compétences techniques obligatoires : Maitrise de l'IDE Flash (Flash 8 et Flash CS3) ActionScript 1/2 avancé minimum (base programmation objet conseillé) Connaissance Flash dynamique (XML, etc.) Connaissance de base PHP/MYSQL. Graphisme, webdesign, ergonomie et animation. Encodage, montage vidéo : After Effect, Adobe Première, format FLV. Compétence non obligatoire mais qui peuvent apporter un gros plus : Illustration et culture artistique Connaissance dans le développement d'applications client/serveur entre un client Flash et un serveur PHP ou autre. (Flash remoting par exemple) Connaissance d'un language de programmation objet (C , C# ou Java). Connaissance pour créer des application Flash "standalone" pour un support Windows/Mac/Linux. Connaissance Flash Media Server ou Red5 ou autre serveur utilisant le protocol RTMP. Connaissance ActionScript 3 / Flex / Air / MXML. Connaissance dans le domaine de l'opensource. Une forte motivation, le respect des délais, une certaine polyvalence, un esprit d'ouverture et l'envie de travailler en équipe seront des critères hautement pris en compte. Rémunération : Négocié en fonction de l'expérience. Disponibilité et contact Disponibilité dès que possible. Contact par courriel à [email protected] [Less]
Posted over 16 years ago by eKameleon
Généralité Cela fait un bon moment maintenant que je suis confronté à divers problèmes concernant la gestion du focus des clips et des champs de texte de saisie dans mes applications (surtout au niveau de l'ordre des tabulations avec la touche TAB ... [More] du clavier). Je sais qu'il existe une classe spécialisée dans ce domaine dans les classes AS2 ou AS3 de Adobe pour Flash... mais j'avoue que j'évite en principe de mélanger mes implémentations personnelles avec celles de Adobe ^_^ Ces derniers temps, étant confronté à plusieurs applications nécessitant une gestion avancée et précise des focus de plusieurs champs de saisies répartis dans plusieurs clips dans mes applications, j'ai enfin mi la main à la patte et j'ai décidé d'implémenter une classe singleton simple disponible en AS2 et en AS3 dans le package asgard.managers.* de l'extension ASGard de VEGAS. La classe TabManager reste donc ma solution simple et efficace pour gérer convenablement les sélections via la touche tabulation de votre clavier des différents buttons, champs de saisies et clips dans vos applications. Utilisation La classe TabManager peut être instanciée mais je vous conseille de privilégier l'utilisation de la méthode statique getInstance() qui renvoi une référence singleton de la classe. import asgard.managers.TabManager ;   var manager:TabManager = TabManager.getInstance() ; La classe TabManager contient quelques méthodes simples qui vous permettrons de regrouper via un identifiant unique plusieurs objets intéractifs. En AS2 vous pourrez regrouper des instancers des classes MovieClip, TextField et Button mais aussi des instances de la classe asgard.display.DisplayObject qui est une classe qui gère les vues d'une application en utilisant la composition sur des références visuelles (il faudra que je vous fasse un tutoriel complet sur ce sujet précis qui est "vaste" et peut difficilement être résumé en quelques lignes dans ce tutoriel). En AS3 vous pourrez regrouper tout simplement tout objet qui hérite de la classe flash.display.InteractiveObject. Voici la liste des propriétés et méthodes de la classe TabManager : La propriété auto Cette propriété permet d'activer ou désactiver le mode automatique du manager. Si le manager est en mode automatique à chaque fois que vous cliquez sur un objet enregistré dans le manager si le groupe de cet objet interactif n'est pas sélectionné il le sera automatiquement. Pour illustrer au mieux cette fonctionnalité je vous propose de voir les exemples à la fin de ce tutoriel. clear() Permet de vider complètement le manager de tous les groupes qu'il contient. contains(id) Renvoi true si le TabManager contient un groupe identifié avec la clé passée en paramètre de la fonction. getCurrent() Renvoi la clé du groupe qui vient d'être sélectionné. getInstance() Méthode statique qui renvoi la référence singleton de la classe TabManager. insert( id , child ) Insère un objet intéractif dans le groupe spécifié par la clé unique 'id'. remove( id , child ) Supprime un objet intéractif dans le groupe spécifié. select( id , defaultChild ) Permet de sélectionner un groupe d'élément graphique en fonction de l'identifiant passé en premier paramètre de la fonction. Par défaut quand un groupe est sélectionné le premier item dans le groupe prend le focus sauf si un objet intéractif est passé en paramètre (defaultChild) et que cet objet appartient bien au groupe sélectionné. Cette méthode lance avant d'activer un groupe la méthode unSelect. Une fois la méthode select invoquée tous les objets interactifs du groupe sélectionné ont une propriété tabEnabled qui vaut true. unSelect() Permet de désélectionner complètement le groupe courant. Une fois la méthode unselect invoquée tous les objets interactifs du groupe qui vient d'être désactivé ont une propriété tabEnabled qui vaut false. Exemple d'utilisation en AS2 import asgard.managers.TabManager ;   var manager:TabManager = TabManager.getInstance() ;   manager.auto = true ;   container1.field1.tabIndex = 1 ; container1.field2.tabIndex = 2 ; container1.field3.tabIndex = 3 ; container1.field4.tabIndex = 4 ;   container2.field1.tabIndex = 2 ; container2.field2.tabIndex = 1 ; container2.field3.tabIndex = 4 ; container2.field4.tabIndex = 3 ;   manager.insert("group1", container1.field1 ) ; manager.insert("group1", container1.field1 ) ; manager.insert("group1", container1.field2 ) ; manager.insert("group1", container1.field3 ) ; manager.insert("group1", container1.field4 ) ;   manager.insert("group2", container2.field1 ) ; manager.insert("group2", container2.field2 ) ; manager.insert("group2", container2.field3 ) ; manager.insert("group2", container2.field4 ) ;   manager.select("group1") ;   Key.addListener( this ) ;   var onKeyDown:Function = function():Void {   var code:Number = Key.getCode() ;   switch( code ) {   case Key.UP : { manager.select("group1") ; break ; }   case Key.DOWN : { manager.select("group1", container1.field2) ; break ; }   case Key.LEFT : { manager.select( "group2" ) ; break ; }   case Key.RIGHT : { manager.select( "group2", container2.field3 ) ; break ; }   }   }   trace("press UP, DOWN, LEFT, RIGHT keys to test the tab manager.") ; Les sources de cet exemple se trouvent dans la branche AS2 du repository du SVN de VEGAS : /AS2/trunk/bin/test/asgard/managers/TabManager.fla Exemple d'utilisation en AS3 import asgard.managers.TabManager ;   var manager:TabManager = TabManager.getInstance() ;   manager.auto = true ;   container1.field1.tabIndex = 10 ; container1.field2.tabIndex = 20 ; container1.field3.tabIndex = 30 ; container1.field4.tabIndex = 40 ;   container2.field1.tabIndex = 2 ; container2.field2.tabIndex = 1 ; container2.field3.tabIndex = 4 ; container2.field4.tabIndex = 3 ;   manager.insert("group1", container1.field1 ) ; manager.insert("group1", container1.field2 ) ; manager.insert("group1", container1.field3 ) ; manager.insert("group1", container1.field4 ) ;   manager.insert("group2", container2.field1 ) ; manager.insert("group2", container2.field2 ) ; manager.insert("group2", container2.field3 ) ; manager.insert("group2", container2.field4 ) ;   manager.select("group1") ;     var onKeyDown:Function = function(e:KeyboardEvent):void {   var code:Number = e.keyCode ;   switch( code ) {   case Keyboard.UP : { manager.select("group1") ; break ; }   case Keyboard.DOWN : { manager.select("group1" , container1.field3 ) ; break ; }   case Keyboard.LEFT : { manager.select("group2") ; break ; }   case Keyboard.RIGHT : { manager.select("group2" , container2.field2 ) ; break ; }   }   }   stage.addEventListener( KeyboardEvent.KEY_DOWN , onKeyDown ) ; Comme vous pouvez le voir l'utilisation AS3 ou AS2 de cette classe est pratiquement identique. Les sources de cet exemple se trouvent dans la branche AS3 du repository du SVN de VEGAS : /AS2/trunk/bin/test/asgard/managers/TabManager.fla Conclusion Voici un premier tutoriel concernant les classes de l'extension ASGard de VEGAS. Vous verrez que ASGard est une extension importante dans VEGAS car elle contient beaucoup d'outils permettant de gérer vos RIAs avec des classes pour vos UIs, vos connexions serveurs ( RTMP, HTML, Remoting, etc..), etc. Je suis en train d'ouvrir une page sur Google Code pour écrire en anglais les tutoriaux concernant ASGard mais aussi pour mettre à votre disposition une "issue list" qui vous permettra de créer des tickets en cas de problèmes. Pour le moment vous pouvez utiliser la "issues list" du google code de VEGAS en cas de problème. N'oubliez pas comme toujours qu'en cas de soucis vous pouvez me contacter ou me poser des questions sur le Google Groups de VEGAS : http://groups.google.com/group/vegasos Et pour les petits nouveaux qui découvrent tous mes outils dans ce framework je vous conseille vivement de lire la procédure d'installation du framework. [Less]
Posted over 16 years ago by eKameleon
Généralité PEGAS est une extension AS2/AS3 de VEGAS, je n'ai pas encore beaucoup parlé de cette extension mais il est temps de commencer des tutoriels concernant cette bibliothèque de code spécialisée. PEGAS possède des fonctionnalités ... [More] spécifiques définies par les packages suivants : pegas.color Manipulation et gestion avancée des couleurs. pegas.draw Ce package contient des outils de dessin avancés utilisant les API de dessin dynamique et permettant la création et l'affichage de dessins complexes via des structures de données ecmascript ou via un document au format SVG. pegas.geom, pegas.maths et pegas.util Ces 3 packages mettent à votre disposition des outils mathématiques et géométriques de bases permettant de gérer des transformations physiques ou 3D dans vos applications. pegas.process Moteur de process permattant de créer des actions et des séquenceurs d'actions dans vos applications. Une action est un objet qui s'éxécute via une méthode "run" (IRunnable) mais qui permet de notifier au moins 2 événements au début et à la fin du process. pegas.transitions Ce package contient des outils pour créer facilement des interpolations numériques simples ou complexes (Tween) dans vos applications. Il contient également un moteur de transitions utilisant toutes les fonctionnalités du package pegas.process. pegas.ui Ce package permet la gestion des double-click(AS2) et la gestion des fonctionnalités avancées liées aux touches du clavier (KeyValidator). Les interpolations (tweens). Une interpolation est un changement d'une valeur numérique dans le temps. Le plus simple exemple d'utilisation d'une interpolation réside dans une petite animation sur un clip sur la scène principale d'une animation flash qui permet de faire bouger le clip entre un point et un autre. En général, la première chose que l'on apprend en utilisant Flash c'est la création des animations sur le scénario de Flash en utilisant sur les formes ou les symboles des interpolations. Malgré l'extrême simplicité d'utilisation de ces interpolations automatiques nous nous rendons rapidement compte qu'un peu de code permet d'aller beaucoup plus loin dans ce domaine. C'est Robert Penner et sa célèbre classe Tween qui a révolutionné réellement la philosophie des flasheurs en leur proposant une solution élégante pour créer des animations en utilisant des équations de mouvement mathématiques permettant de créer des mouvements naturels et non linéaires. Adobe a vite intégré cette fonctionnalité dans Flash MX 2004 pour donner du mordant à ses composants et depuis la classe mx.transitions.Tween reste un grand classique. Malgré tout l'implémentation de Adobe reste sympathique mais de nombreux développeurs se sont essayés dans l'implémentation d'autres solutions proposant au final le même résultat. J'ai donc moi même très rapidement crée ma propre implémentation de l'algorithme d'interpolation basé sur des équations de mouvements en gardant l'esprit d'origine de la classe de Robert Penner mais en changeant légèrement le moteur interne et l'étendu des possibilité de la classe originelle. Dans PEGAS j'ai donc décidé dans le package pegas.transitions d'implémenter 2 classes TweenLite et Tween A noter que tous les exemples de ce tutoriel peuvent être testés dans le repository de VEGAS dans le répertoire AS2/trunk/bin/test/pegas/transitions La classe pegas.transitions.TweenLite Cette classe possède pratiquement toutes les fonctionnalités de la classe mx.transitions.Tween de Adobe. Elle permet de controler sur un objet une propriété numérique et de la modifier dans un certain intervalle de temps donné. Voici un exemple basique d'utilisation de cette classe. import pegas.transitions.TweenLite ; import pegas.transitions.easing.* ;   var tw:TweenLite = new TweenLite(mc, "_x", Bounce.easeOut, mc._x, 550, 1, true) ; tw.run() ; Voyons de plus prêt la fonction constructeur de la classe TweenLite : var tw:TweenLite = new TweenLite( obj:Object , prop:String , easing:Function , begin:Number , finish:Number , duration:Number , useSeconds:Boolean , auto:Boolean ) ; obj : La référence de l'objet que l'on souhaite modifier (pas forcément un MovieClip, tout clip qui contient une propriété numérique). prop : Une chaine de caractère qui correspond au nom de la propriété numérique que l'on souhaite modifier. easing : L'équation de mouvement (easing equation) que l'on souhaite utiliser pendant l'interpolation. begin : La valeur de départ de la propriété numérique. finish : La valeur finale de la propriété numérique à la fin de l'interpolation. duration : La durée de l'interpolation en frames/secondes par défault mais également en secondes si l'argument "useSeconds" est true. useSeconds : Indique si cet argument est "true" que la durée de l'interpolation doit être compatibilisée en seconde. Si ce paramètre est "false" l'interpolation utilise une durée en frames/secondes. auto : Indique si l'argument est "true" que l'interpolation doit démarée automatiquement une fois l'instance créée. Comme vous pouvez le remarquer, contrairement à la classe Tween de Adobe, même si la création de l'instance de type TweenLite ressemble beaucoup à la création d'une instance de la classe mx.transitions.Tween, l'effet de transitions n'est pas automatiquement lancé une fois l'instance créée dans votre code. Il faut utiliser la méthode "run" ou "start" de l'instance pour lancer l'interpolation ou utiliser le dernier paramètre facultatif du constructeur de la classe en lui passant une valeur booléenne "true". En fait j'ai décidé de ne pas forcer le lancement automatique de l'interpolation pour une raison simple, la classe TweenLite implémente l'interface pegas.process.Action et indirectement l'interface vegas.core.IRunnable. Ces 2 interfaces indiquent que la classe TweenLite est à la fois une commande et à la fois un process. C'est à dire qu'il est possible d'utiliser les tweens de PEGAS dans un système de séquenceur complet qui permet d'organiser et de maitriser plus finement vos animations et effets de transitions dans vos applications. Aussi je préfère avoir un controle complet sur les instances de la classe TweenLite (ainsi que la classe pegas.transitions.Tween). Exemple d'utilisation du constructeur de la classe TweenLite avec l'option "auto" : import pegas.transitions.Tween ; import pegas.transitions.easing.* ;   var tw:Tween = new Tween (mc, "_x", Bounce.easeOut, mc._x, 600, 24, false, true) ; Remarque : Comme vous pourrez le remarquer je me suis permis de placer dans le package pegas.transitions.easing.* du framework les classes de easing de Robert Penner (ces classes sont soumises à la licence officielle de Robert Penner). Système évènementiel de la classe TweenLite et de la classe Tween Basé sur le modèle événementiel de VEGAS, la classe TweenLite possède des événements spécifiques en fonction des différentes phases de l'interpolation. La classe TweenLite (comme la classe Tween) notifie des événements de type pegas.events.ActionEvent. Voici les types d'événements que l'on peut écouter sur une tween : ActionEvent.CHANGE : invoqué pendant l'interpolation avec une fréquence définie par le moteur de l'interpolation. ActionEvent.FINISH : invoqué à la fin de l'interpolation. ActionEvent.LOOP : invoqué lorsque la tween utilise son option "looping" (boucle à la fin de l'interpolation et repart de son point de départ) ActionEvent.RESUME : Invoqué lorsque l'utilisateur arrête l'interpolation avec la méthode stop() et qu'il relance l'interpolation en repartant de sa positon courante. ActionEvent.START : Invoqué au lancement de l'interpolation. ActionEvent.STOP : Invoqué lorsque l'utilisateur arrête l'interpolation avant la fin de celle ci. Les 2 événements ActionEvent.FINISH et ActionEvent.START assurent l'implémentation de l'interface pegas.process.Action et de la classe abstraite AbstractAction. Exemple d'utilisation du modèle évènementiel de la classe TweenLite : import pegas.events.ActionEvent ; import pegas.transitions.TweenLite ; import pegas.transitions.easing.Elastic ;   import vegas.events.EventListener ; import vegas.events.Delegate ;   var onDebug:Function = function( e:ActionEvent ):Void { trace ( e.getType() ) ; }   var debug:EventListener = new Delegate( this , onDebug ) ;   var tw:TweenLite = new TweenLite (mc, "_x", Elastic.easeOut, mc._x, 600, 2, true, true) ; tw.addEventListener( ActionEvent.START , debug ) ; tw.addEventListener( ActionEvent.CHANGE , debug ) ; tw.addEventListener( ActionEvent.FINISH , debug ) ; La propriété booléene "looping" de la classe TweenLite. import pegas.events.ActionEvent ; import pegas.transitions.TweenLite ; import pegas.transitions.easing.Back ;   import vegas.events.Delegate ;   var loop:Function = function( e:ActionEvent ):Void { trace( e ) ; }   var tw:TweenLite = new TweenLite( mc, "_x", Back.easeOut, mc._x, 550, 1, true , true ) ; tw.addEventListener( ActionEvent.LOOP , new Delegate(this, loop) ) ; tw.looping = true ; La méthode continueTo() de la classe TweenLite Cette méthode relance l'interpolation avec un nouvelle valeur d'arrivée au but et elle permet également de changer la durée de l'interpolation. Exemple d'utilisation de la méthode continueTo : import pegas.events.ActionEvent ; import pegas.transitions.TweenLite ; import pegas.transitions.easing.* ;   import vegas.events.Delegate ;   var continueTo:Function = function( e:ActionEvent ):Void { var target:TweenLite = TweenLite(e.getTarget()) ; trace(e " continueTo(100,2)" ) ; target.continueTo( 100 , 2 ) ; }   var tw:TweenLite = new TweenLite( mc, "_x", Bounce.easeOut, mc._x, 550, 1, true ) ; tw.addEventListener( ActionEvent.FINISH , new Delegate(this, continueTo) , null, null, true ) ; // auto remove the listener tw.run() ; La méthode yoyo() de la classe TweenLite La méthode yoyo permet de jouer l'interpolation en inversant sa valeur d'arrivée par sa valeur de départ. Exemple d'utilisation de la méthode yoyo() de la classe TweenLite : import pegas.events.ActionEvent ; import pegas.transitions.TweenLite ; import pegas.transitions.easing.* ;   import vegas.events.Delegate ;   var yoyo:Function = function( e:ActionEvent ):Void { var target:TweenLite = TweenLite(e.getTarget()) ; trace(e " yoyo()" ) ; target.yoyo() ; }   var tw:TweenLite = new TweenLite( mc, "_x", Bounce.easeOut, mc._x, 550, 2, true ) ; tw.addEventListener( ActionEvent.FINISH , new Delegate(this, yoyo) ) ; tw.run() ; La classe TweenEntry La différence majeur entre la classe mx.transitions.Tween de Adobe et la classe TweenEntry. Dans les classes Tween et TweenLite de PEGAS j'utilise un moteur interne basé sur une instance ou des instances de type TweenEntry. Une TweenEntry permet de définir le nom de la propriété numérique que l'on veut modifier, la valeur de fin et de début et l'équation de mouvement de l'interpolation. Exemple d'utilisation d'une instance de type TweenEntry avec la propriété virtuelle "tweenEntry" : import pegas.transitions.TweenEntry ; import pegas.transitions.TweenLite ; import pegas.transitions.easing.Back ;   import vegas.events.Delegate ;   var tw:TweenLite = new TweenLite( mc ) ; tw.duration = 1 ; tw.useSeconds = true ;   tw.tweenEntry = new TweenEntry( "_x" , Back.easeOut, mc._x , 500 ) ;   tw.start() ; A noter qu'il est possible de configurer la TweenLite avec la méthode setTweenEntry. Cette méthode met à jour automatiquement la référence de type TweenEntry utilisée par la TweenLite. import pegas.transitions.TweenEntry ; import pegas.transitions.TweenLite ; import pegas.transitions.easing.Back ;   import vegas.events.Delegate ;   var tw:TweenLite = new TweenLite( mc ) ; tw.duration = 1 ; tw.useSeconds = true ;   tw.setTweenEntry( "_x" , Back.easeOut, mc._x , 500 ) ;   tw.start() ; La classe pegas.transitions.Tween La classe Tween du package pegas.transitions fonctionne à première vue comme la classe TweenLite mais permet d'aller plus loin en proposant une fonctionnalité multi-tween via un modèle interne. Voici un exemple basique d'utilisation de cette classe : import pegas.transitions.Tween ; import pegas.transitions.TweenEntry ; import pegas.transitions.TweenModel ;   import pegas.transitions.easing.Back ; import pegas.transitions.easing.Bounce ;   var tweens:TweenModel = new TweenModel() ; tweens.insert( new TweenEntry( "_x" , Bounce.easeOut , mc._x , 550 ) ) ; tweens.insert( new TweenEntry( "_y" , Back.easeOut , mc._y , 300 ) ) ; tweens.insert( new TweenEntry( "_rotation", Bounce.easeOut , mc._rotation , 360 ) ) ;   var tw:Tween = new Tween(mc) ; tw.model = tweens ; tw.duration = 2 ; tw.useSeconds = true ;   tw.run() ; Constructeur de la classe Tween La fonction constructeur de la classe Tween permet de définir l'interpolation de 2 manières différentes. 1 - Il est possible tout d'abord d'utiliser une instanciation identique à celle de la classe TweenLite. var tw:Tween = new Tween( obj, prop:String, e:Function, b:Number, f:Number, d:Number , u:Boolean, auto:Boolean) ; 2 - La second façon d'instancier la classe permet de définir directement un modèle qui permettra de préparer la multi-interpolation. var tw:Tween = new Tween( obj, entries , d:Number , u:Boolean, auto:Boolean ) ; Le paramètre "entries" peut être un Array ou une objet de type TweenModel. import vegas.events.Delegate ;   import pegas.events.ActionEvent ; import pegas.transitions.Tween ; import pegas.transitions.TweenEntry ; import pegas.transitions.easing.* ;   var onDebug:Function = function( e:ActionEvent ):Void { trace ( e.getType() ) ; }   var entries:Array = [ new TweenEntry("_x" , Expo.easeOut , mc._x , 600 ) , new TweenEntry("_y" , Back.easeOut , mc._y , 350 ) , new TweenEntry("_rotation" , Regular.easeOut , 0 , 360*2 ) , new TweenEntry("_xscale" , Back.easeInOut , mc._xscale , 150 ) ] ;   var tw:Tween = new Tween( mc , entries , 2 , true ) ;   tw.addGlobalEventListener( new Delegate( this, onDebug ) ) ;   tw.start() ; Utilisation des entrées de type TweenEntry pour configurer à tout moment toutes les propriétés de la multi-interpolation. Comme la classe TweenLite, la classe Tween utilise des TweenEntry pour définir les différentes modifications qui vont s'opérer sur l'objet au cours du temps. Il est donc possible de définir ou d'ajouter à tout moment (même pendant l'interpolation) une TweenEntry avec plusieurs méthodes simples : import pegas.transitions.Tween ; import pegas.transitions.TweenEntry ; import pegas.transitions.easing.* ;   var tw:Tween = new Tween (mc, "_rotation", Strong.easeOut, 0, 360) ; tw.duration = 4 ; tw.useSeconds = true ;   tw.insertProperty("_x", Bounce.easeOut, mc._x, 600) ;   tw.insert( new TweenEntry("_y", Back.easeOut, mc._y, 250)) ;   tw.start() ;   trace("Press a key to remove _rotation property during the animation and change the _y property entry.") ;   Key.addListener(this) ;   var onKeyDown:Function = function () { tw.setTweenEntry( "_y", Back.easeOut, mc._y, 0 ) ; tw.removeProperty("_rotation") ; } Les méthodes insertProperty(), insert(entry:TweenEntry), setTweenEntry(), remove(entry:TweenEntry) et removeProperty() permettent d'agir rapidement sur n'importe quelle propriété de l'interpolation. La classe TweenModel La classe Tween utilise un modèle interne de type pegas.transitions.TweenModel qui implémente parfaitement l'implémentation proposée par l'interface andromeda.model.IModel. La classe TweenModel permet d'enregistrer dans une Map interne (HashMap) toutes les TweenEntry nécessaires pendant l'interpolation. La classe TweenModel possède de nombreuses méthodes et peut être cablée sur le flux global de l'application en cas de besoin. Exemple d'utilisation de la classe TweenModel : import pegas.transitions.easing.* ; import pegas.transitions.Tween ; import pegas.transitions.TweenEntry ; import pegas.transitions.TweenModel ;   var tm:TweenModel = new TweenModel() ;   tm.insert(new TweenEntry("_x", Bounce.easeOut, mc._x, 550)) ; tm.insert(new TweenEntry("_y", Back.easeOut, mc._y, 300)) ;   var tw:Tween = new Tween(mc) ;   tw.model = tm ; tw.duration = 4 ; tw.useSeconds = true ;   tw.start() ;   trace ("press a key to test other tweenProvider") ; Key.addListener(this) ; var onKeyDown:Function = function () { tw.model = [ new TweenEntry("_x", Bounce.easeOut, mc._x, 40) , new TweenEntry("_y", Bounce.easeOut, mc._y, 25) , new TweenEntry("_rotation", Bounce.easeOut, mc._rotation, 360) ] ; if (!tw.running) { tw.start() ; } } Utilisation de la méthode start(), resume() et stop() Les classes TweenLite et Tween ont toutes les 2 les méthodes start, stop et resume qui permettent de controller la progression de l'interpolation. import pegas.events.ActionEvent ; import pegas.transitions.Tween ; import pegas.transitions.TweenEntry ; import pegas.transitions.easing.* ;   import vegas.events.Delegate ;   var onDebug:Function = function( e:ActionEvent ):Void { trace ( e.getType() ) ; }   var entries:Array = [ new TweenEntry( "_x" , Expo.easeOut , mc._x , 600 ) , new TweenEntry( "_y" , Back.easeOut , mc._y , 350 ) , new TweenEntry( "_rotation" , Regular.easeOut , 0 , 360*2 ) , new TweenEntry( "_xscale" , Back.easeInOut , mc._xscale , 150 ) ]   var tw:Tween = new Tween( mc , entries ) ; tw.addGlobalEventListener( new Delegate( this , onDebug ) ) ; tw.duration = 1.5 ; tw.useSeconds = true ;   tw.start() ;   Key.addListener(this) ; onKeyDown = function () { if (tw.running) { tw.stop() ; } else { var isResume:Boolean = tw.resume() ; if (!isResume) tw.start() ; } } Utiliser un séquenceur avec les classes Tween et TweenLite Comme je l'ai dit plus haut, la classe Tween et la classe TweenLite implémentent l'interface Action et par leur héritage sont des extensions de la classe SimpleAction compatible avec la classe pegas.process.Sequencer. Comme tous les process implémentés avec l'interface Action dans VEGAS et ses extensions il est donc possible de cumuler plusieurs tweens et de les lancer les unes après les autres. Exemple d'utilisation d'un séquenceur : import vegas.events.Delegate ; import vegas.events.EventListener ;   import pegas.events.ActionEvent ; import pegas.process.Sequencer ; import pegas.transitions.Tween ; import pegas.transitions.TweenEntry ; import pegas.transitions.easing.* ;   var onDebug:Function = function( e:ActionEvent ):Void { var type:String = e.getType() ; var target:Object = e.getTarget() ; trace ( target.size() " : " type ) ; if ( type == ActionEvent.FINISH ) { var clone:Sequencer = s.clone() ; clone.addGlobalEventListener( debug ) ; clone.run() ; } }   var debug:EventListener = new Delegate(this, onDebug) ;   var tween1:Tween = new Tween( mc ) ; tween1.duration = 1 ; tween1.useSeconds = true ; tween1.insert( new TweenEntry("_x", Expo.easeOut, mc._x, 600) ) ; tween1.insert( new TweenEntry("_y", Back.easeOut, mc._y, 320) ) ; tween1.insert( new TweenEntry("_rtweenation", Regular.easeOut, 0, 600) ) ;     var tween2:Tween = new Tween( mc ) ; tween2.duration = 1 ; tween2.useSeconds = true ; tween2.insert( new TweenEntry("_x", Expo.easeOut, 600, 325) ) ; tween2.insert( new TweenEntry("_y", Expo.easeOut, 320, 40) ) ; tween2.insert( new TweenEntry("_rtweenation", Regular.easeOut, 0, -360 ) ) ;   tween3.duration = 1 ; tween3.useSeconds = true ; tween3.insert( new TweenEntry("_x", Expo.easeOut, 325, 30 ) ) ; tween3.insert( new TweenEntry("_y", Back.easeOut, 40, 220) ) ;   var tween4:Tween = new Tween( mc ) ; tween4.duration = 2 ; tween4.useSeconds = true ; tween4.insert( new TweenEntry("_x", Bounce.easeOut, 30, 620) ) ; tween4.insert( new TweenEntry("_y", Back.easeOut, 220, 30) ) ;   var s:Sequencer = new Sequencer() ; s.addAction(tween1) ; s.addAction(tween2) ; s.addAction(tween3) ; s.addAction(tween4) ;   var clone:Sequencer = s.clone() ; clone.addGlobalEventListener( debug ) ; clone.run() ; Remarque : Toutes les classes de type Action sont cloneables (IClonable) et j'utilise dans l'exemple ci-dessus cette fonctionnalité pour vider progressivement un clone du séquenceur original et ainsi pouvoir le réutiliser plusieurs fois. La classe pegas.transitions.EasingController Pour faciliter l'utilisation des tweens dans mes application j'ai décidé de mettre en place une classe singleton EasingController simple qui permet de stocker en fonction d'un identifiant unique un type d'équation de mouvement (objet de type Function). J'utilise beaucoup ce singleton dans mes applications pour simplifier la mise en place d'une configuration globale de mon application et ainsi je peux facilement cibler selon les cas l'équation de mouvement que je désire. Exemple d'utilisation : import pegas.transitions.easing.* ; import pegas.transitions.EasingController ; import pegas.transitions.TweenLite ;   var tw:TweenLite ; var easing:Function ; var controller:EasingController = EasingController.getInstance() ;   controller.insert( "back_ease_out" , Back.easeOut ) ; controller.insert( "bounce_ease_out" , Bounce.easeOut ) ; controller.insert( "elastic_ease_out" , Elastic.easeOut ) ;   Key.addListener(this) ;   var onKeyDown:Function = function():Void {   tw.stop() ;   var code:Number = Key.getCode() ;   switch( code ) { case Key.LEFT : { easing = controller.getEasing( "back_ease_out" ) ; break ; } case Key.RIGHT : { easing = controller.getEasing( "bounce_ease_out" ) ; break ; } case Key.UP : { easing = controller.getEasing( "elastic_ease_out" ) ; break ; } case Key.DOWN : { // use a default value if the easing is isn't register in the easing controller   break ; } }   tw = new TweenLite( mc, "_x" , easing, 100, 500, 2 , true, true ) ; // auto start   }   easing = controller.getEasing( "elastic_ease_out" ) ; tw = new TweenLite( mc, "_x" , easing, 100, 500, 2 , true ) ;   tw.start() ; Conclusion L'implémentation des classes TweenLite et Tween de PEGAS sont pas les implémentations les plus rapides qui existent actuellement au sein de la communauté mais j'avoue me sentir à l'aise avec elles et cela me suffit Bien entendu il y a de forte chance que dans l'avenir j'ai besoin d'une implémentation plus rapide et je verrais alors si je peux ajouter une classe SpeedTween dans le framework... surtout que la version AS3 de ces classes n'est pas encore implémentée et peut me pousser à changer ou améliorer le code AS2. Comme toujours pour toute question sur ce tutoriel vous pouvez vous inscrire sur le Google Groupes de VEGAS : http://groups.google.com/group/vegasos Si vous trouvez des bugs n'hésitez pas à créer un ticket sur la issue liste du projet : http://code.google.com/p/pegas/issues/list Et pour les petits nouveaux qui découvrent tous mes outils dans ce framework je vous conseille vivement de lire la procédure d'installation du framework. [Less]
Posted over 16 years ago by eKameleon
Une bonne surprise ce soir en surfant sur le net car je viens de trouver un tout nouveau projet opensource de serveur RTMP avec le serveur Milenia Grafter Server qui annonce un maximum de possibilités avec un minimum de poids avec seulement poids ... [More] record annoncé de 64 Kbyte. Le serveur en est pour le moment à sa version 0.5 (beta) mais semble posséder tous les arguments indispensables d'un serveur RTMP pour un client flash : Diffusion live Audio/Video streaming Enregistrement temps réel en streaming. Moteur de streaming complet Communication client/server légère Client mode Communication Données/Audio/Video serveur vers un autre serveur (clustering) Console d'administration Ce serveur est codé comme RED 5, Wowza ou ElectroServer en JAVA et nécessite donc l'installation de la virtual machine JAVA 1.5 minimum. Le projet est sous licence GNU General Public License. Milan Toth l'auteur Hongrois de ce serveur indique que ce projet est né tout simplement de ces besoins pour produire des jeux multijoueurs avec Flash donc on peut le féliciter de nous faire partager son travail. L'API serveur en JAVA (même si je continue à avoir du mal avec ce langage) semble simple à utiliser. On trouve même en lisant rapidement la documentation une classe Client (côté serveur) très complète avec des propriétés agent, referrer (important dans FMS), ip, etc.. Et surtout 2 propriétés très intéressantes hasVideo, hasAudio qui permettent de savoir si un utilisateur est en train de diffuser son microphone ou sa webcam dans les 5 dernières secondes lors de l'appel de cette propriété. Nous pouvons voir également une classe Timer qui peut s'avérer très pratique. A noter pour finir que ce serveur fonctionne sous le protocol AMF0 et que si l'on souhaite utiliser ce serveur avec de l'AS3 il faut absolument penser à changer l'encodage par défaut de la classe NetConnection en utilisant le protocol AMF0 et non plus le protocol AMF3. Je n'ai pas encore eu le temps de m'essayer réellement avec ce serveur et je compte bien m'y mettre dès que possible. La seule chose que je n'ai pas encore réussi à trouver dans les sources du projet c'est le moyen de changer l'ip du serveur par défaut ? Si quelqu'un à une idée la solution à ce petit problème je suis preneur [Less]