Applications Flash avec Facebook Graph API

En cours de modification, Facebook a changé la méthode de passage du token.

Dernièrement, enfin ca fait un peu de temps maintenant, Facebook à mis en place sa nouvelle API : Graph. Donc aujourd'hui vous avez deux possibilités pour créer une application Facebook en Flash :

  • avec l'ancien SDK, et donc là vous pouvez continuer à utiliser l'API AS3 Facebook crée par Adobe.
  • avec Graph, d'où le titre de ce billet.

Facebook graph api

J'utilise la méthode de rendu "Iframe".

La première chose à faire est de tester si l'utilisateur qui visite l'application l'a déjà installée ou non. Pour cela, on utilise un bout de code FBML :






Donc là, facebook fait tout pour vous. En gros, si l'utilisateur n'a pas déjà installé l'application, facebook le redirige vers une page où il doit accepter l'application avec différentes permissions supplémentaires (le paramètre scope). Pour la liste des permissions, je vous laisse parcourir la doc.

Je ne conseille pas d'ajouter toutes les permissions nécessaires à votre application sur ce premier écran. Vous pourrez demander plus tard des autorisations supplémentaires. Vous risquez de le faire fuire dans le cas contraire (on y reviendra après)...

Une fois cliquer sur "autoriser", facebook redirige vers votre superbe application.

Grâce aux balises FBML, on ajoute le shockwave dans la page :


Facebook utilise dorénavant le protocole OAuth 2.0, comme Youtube par exemple, pour l'authentification. Si l'utilisateur a bien autorisé l'application (en fait il n'a pas le choix), le flash reçoit alors une FlashVar nommée "session" encodée en JSON. Cet objet contient un "access token" qui va vous permettre d'interroger Facebook via Graph afin de récupérer les données "publiques" de l'utisateur (sinon, il faut demander l'autorisation). Le token est valable 24h.

var o:Object = JSON.decode(loaderInfo.parameters.session);
_token = o.access_token;

Facebook retourne les résultats au format JSON. J'utilise l'as3CoreLib pour le décoder.
On implémente une petite méthode raccourcie qu'on utilisera tout le temps où on passe ce fameux token en paramètre dans l'url :

private function _callGraph(method:String):URLLoader
{
	var urlLoader:URLLoader = new URLLoader();
	urlLoader.load(new URLRequest("https://graph.facebook.com/" + method + "?access_token=" + _token));
	return urlLoader;
}

Puis dès lors qu'on souhaite, par exemple récupérer les données de l'utilisateur "loggué", on utilise la methode "me" (me étant l'utilisateur actuel :

var urlLoader:URLLoader = _callGraph("me");
urlLoader.addEventListener(Event.COMPLETE, _getFriendsComplete);

_callGraph("/me/friends"); // les amis de l'utilisateur actuel
_callgraph("gwenn.guihal"); // mes infos (gwenn.guihal ou 567172079)
_callgraph("gwenn.guihal/friends"); // mes amis

Voici la liste des actions possibles : http://developers.facebook.com/docs/api

L'utilisateur peut restreindre l'accès à son profil, et par exemple empêcher de lister les "likes". Si on en a besoin, on lui demande d'autoriser. Pour cela, on utilise Javascript :
En plus de l'objet session, Facebook nous donne un identifiant LocalConnection.

_fb_local_connection = _loaderInfo.parameters.fb_local_connection;

Grâce à ce dernier, on va pouvoir appeller du JS sur la page Facebook (nos fonctions JS et celles de Facebook). Voici une méthode raccourci :

private function _callJS(method : String,arg:Array = null) : void
{
	if (!_localConnection) // private variable
	{
		_localConnection = new LocalConnection();
	}
	
	_localConnection.send(_fb_local_connection, "callFBJS", method, arg);
}

Donc pour afficher une popup de demande de permissions :

_callJS("Facebook.showPermissionDialog", ['likes,email,publish_stream,...']);

La liste des permissions

Après, tout se trouve dans la doc http://developers.facebook.com/docs/ ou sur Internet.

Encore un truc pas mal, si vous ne l'avez pas déjà deviné : une fois que vous avez un token valide, vous pouvez interroger facebook pendant 24h, via par exemple le navigateur :

https://graph.facebook.com/gwenn.guihal?access_token=_TOKEN_

Et enfin, si vous compilez en Flash 9 et si vous avez des erreurs de flux, compilez en Flash 10.

Préchargement avec le compilateur Flex en pure AS3 sur un seul SWF (2 frames)

Dans l'IDE de Flash, la manière de preloader le site avec un joli loading est d'exporter les assets sur la deuxième frame et donc sur la première frame implémenter le chargement :

public var myLoading:MovieClip;
		
public function Main()
{
	loaderInfo.addEventListener(ProgressEvent.PROGRESS, _progressHandler);
	loaderInfo.addEventListener(Event.COMPLETE, _completeHandler);
}

private function _progressHandler(event:ProgressEvent):void
{	
	var percent:Number = event.bytesLoaded / event.bytesTotal;
	myLoading.percent_txt.text = int(percent *100) + "%";
}

private function _completeHandler(event:Event):void
{
	gotoAndStop(2); // lance le site
}

Lorsqu'on compile un projet AS3 avec le compilateur de Flex, cette méthode semble compromise (projet en pure AS3, sans flex). Une solution consite à créer un premier SWF qui va charger votre application. Cependant, pour causes de performances je suis pas fan (j'évite au maximum ajouter des swf dans des swf).
Après quelques recherches, ici et puis surtout , voici une autre solution : Le compilateur flex propose un argument "-frame" qui permet de rajouter des frames sur la timeline avec un label et une classe (il faut que votre main hérite de MovieClip, c'est mieux).

Dans Main.as, qui est la classe de base de l'application/site, on ajoute, via la méthode "addFrameScript", du code sur les frames comme si on était dans la timeline de l'IDE : Sur la première frame le loading, puis sur la deuxième le "go" de l'application. Pour cela, on part du principe que la base du site/application est implémentée dans une classe à part, par exemple Site.as.

Le but de la manœuvre consiste à exporter la classe Site, et donc toutes les classes associées dans la deuxième frame. On ajoute
" -frame START Site"
aux arguments de compilation. Cet argument ajoute une frame sur la timeline de Main, dont le label est "START" mais surtout va exporter la classe Site sur cette même frame, donc sur la frame 2 !

Donc Main.as va ressembler à ça :

public function Main()
{
	addFrameScript(0,frame1); // ajoute du code sur la frame 1
	addFrameScript(1,frame2); // ajoute du code sur la frame 2
}

private function frame1():void
{
	loadingClip = new LoadingClip(); // loadingClip est un clip contenant un champ texte
	addChild(loadingClip);
	// listeners de chargement
	loaderInfo.addEventListener(ProgressEvent.PROGRESS, _progressHandler);
	loaderInfo.addEventListener(Event.COMPLETE, _completeHandler);
}


private function _progressHandler(event:ProgressEvent):void
{	
	var percent:Number = event.bytesLoaded / event.bytesTotal;
	loadingClip.text_txt.text = int(percent *100) + "%";
}

private function _completeHandler(event:Event):void
{
	loaderInfo.removeEventListener(ProgressEvent.PROGRESS, _progressHandler);
	loaderInfo.removeEventListener(Event.COMPLETE, _completeHandler);
	
	removeChild(loadingClip);
	gotoAndStop(2); // on va sur la frame 2 (la méthode frame2 est appellée)
}

private function frame2():void
{
	// création manuelle d'une intance de Site
	var SiteClass:Class = getDefinitionByName("Site") as Class;
	addChild(new SiteClass());
}
Si lors de l'appel de la méthode frame2, on avait écrit :
private function frame2():void
{
	var site:Site = new Site();
	addChild(site);
}
On aurait importé la classes Site + ses associations dans Main, ce qui aurait rendu obselète notre chargement. On retrouve donc la classe Site et on l'instancie manuellement au runtime.

Je mets un exemple ici, j'utilise FDT mais la méthode est similaire sur FlashDevelop ou bien Flash Builder. Mes assets (clip graphiques) sont crées dans l'IDE Flash, puis exporter dans un SWC que j'inclue à la compilation (ajouter au buildPath). De cette manière, je peux compiler avec le compilateur Flex (beaucoup plus rapide) et en plus avoir l'autocomplétion sur mes assets !
Le beurre et l'argent du beurre !

Nommer les boucles en AS3

Hola,

Imaginons 2 boucles imbriquées :

var searchedVo:MyVo;

for each (var voList:Array in superVoList) // firstloop
{
	for each (var vo:MyVo in voList) // secondloop
	{
		if (vo.name == "raimond")
		{
			searchedVo = vo;
			break;
		}
	}
}
Une fois le résultat escompté, la seconde boucle sera détruite mais la première continuera... Pas terrible.
Heureusement, il est possible d'associer un label sur chacune des boucle, et spécifier lors du "break", qu'elle boucle faut-il stopper.
label : for (...)

En reprenant notre code précédent, ça donne ça :

firstLoop : for each (var voList:Array in superVoList) // firstloop
{
	secondLoop : for each (var vo:MyVo in voList) // secondloop
	{
		if (vo.name == "raimond")
		{
			break firstLoop; // kill firstloop
		}
	}
}
Et là, on passe illico à la suite, les DEUX boucles sont stoppées.

Rescue the Puppets, le site qui a la classe...

Hello

Si vous connaissez le groupe Puppetmastaz, vous serez heureux d'apprendre qu'un site les concernant vient tout juste de sortir. Vous allez devoir libérer les puppets une par une dans un décor très soigné. Un site classe, un site à voir.

Puppetmastaz rescuethepuppets

Coordonnées globales

Hello,

Erratum

Après quelques recherches au fond de moi-même, j'ai, enfin je crois avoir compris comment utiliser la méthode localToGlobal dans mon cas :
J'ai un clip Albert sur ma scène, il contient un clip Bertand qui contient lui un clip Clément. Je veux, dans Bertrand, connaitre la position de Clément par rapport à la scène (stage). Il suffit de faire :

// je suis dans Bertand.as, classe liée au clip Bertrand
var pt:Point = clement_mc.localToGlobal(new Point(0,0)));

Le point 0,0 représente le point 0,0 dans clément_mc. Et donc, Flash me retourne ce point mais relativement à la scène. Bien entendu, il s'agit du même résultat qu'obtenu avec la classe Coord.as. Cette dernière n'est donc plus trop utile... Mais bon, je laisse tout de même la suite...

Je ne sais pas vous, mais moi, j'ai pas encore tout compris aux fonctions globalToLocal et localToGlobal... En tout cas elles ne fonctionnent pas toujours comme j'aimerais l'entendre...

Par exemple, dans un projet Flash, vous avez besoin de tooltips. Le tooltip doit toujours se trouver au dessus de tous les autres clips. Donc, logiquement, il est placé sur la scène, tout au dessus. Maintenant, au rollover de votre bouton, le tooltip doit venir se placer sur votre bouton ou pas loin. Le problème, c'est que votre bouton, est placé dans un clip, qui est lui même placé dans un clip, [...], qui est enfin placé sur la scène. On doit donc donner au tooltip les coordonnées du bouton relatives à la scène.
Voici une simple classe, amenée à être complétée avec d'autres fonctionnalités qui va faire le travail pour vous :

package fr.myrddin.utils 
{
	import flash.display.DisplayObject;
	import flash.geom.Point;		


	public class Coord 
	{
		/**
		 * Renvoie les coordonnées d'un clip par rapport à la scène
		 * @param $mc Le clip
		 * @return Les coordonées du clip par rapport à stage
		 */
		public static function getCoordGlobal($mc:DisplayObject):Point
		{
			var pt:Point = new Point();
			
			return incrementeCoord($mc,pt);
		}
		
		private static function incrementeCoord($mc:DisplayObject,$pt:Point):Point
		{
			$pt.x += $mc.x;
			$pt.y += $mc.y;
			
			if ($mc.parent)
			{
				return incrementeCoord($mc.parent,$pt);
			}
			else
			{
				return $pt;
			}
			
		}
	}
}

Et quand vous en avez besoin :

var btn:MovieClip = $e.currentTarget as MovieClip;
var pt:Point = Coord.getCoordGlobal(btn);

La classe est téléchargeable ici

Expérimentation sur Five3D

Bonjour

APrès Papervision, j'ai voulu tester un peu Five3D, le moteur 3D vectoriel de Mathieu Badimon via un mini (vraiment mini) jeu.

J'ai trouvé Five3D nettement moins gourmand en ressources que Papervision, en tout cas en ce qui concerne les graphiques vectoriels. Papervision décline le graphisme vectoriel en bitmap alors que Five3D le conserve. (Je n'ai pas encore testé VectorVision...).
Cependant, on arrive au même problèmes de latence dès lors qu'on travaille avec les bitmaps. En effet dans sa nouvelle version, Five3D comprend une classe Bitmap3D.

A l'utilisation, j'ai trouvé five3D très simple d'utilisation, son fonctionnement est très proche de l'implémentation de l'AS3 :

body.graphics3D.beginFill(0x68bb21);
body.graphics3D.drawRoundRect(-20, 0, 40, 40, 4, 4);
body.graphics3D.endFill();
Par contre, ses fonctionnalités sont plus limitées, pour le moment en tout cas. Il est impossible de créer des dégradés ou d'ajouter dans la displayList d'un Sprite3D un élément vectoriel 2D (dessiné précédemment dans l'API de Flash par exemple). La classe Sprite2D le permet, mais les possibilités 3D sont limités (rotation uniquement sur l'axe Z).
Le Z-sorting est bien géré ainsi que le Flat-shading. Je n'ai malheureusement pas testé la gestion de la typo...

container.childrenSorted = true; // Z-sorting
me.flatShaded = true; // Flat shading
Five3D example and sources

Déplacez-vous avec les flèches du clavier et allez toucher les items clignotants...

Pour conclure ce petit test, j'ai trouvé Five3D très agréable à utiliser et le rendu est superbe comparé à un Papervision. Vivement les prochaines versions et bravo à son créateur !

Visualiser l'exemple. Télécharger les sources.

Google indique le nombre de résultats des mots clés

Une surprise sympa ce soir, l'image parle d'elle même...

Boules rebondissantes (Papervision3D + Shadows + WOW-Engine)

Après avoir vu l'article de Andy Zupko à propos des ombres dans papervision et le moteur physique WOW-Engine de Seraf, je me suis dit, j'ai bien envie d'essayer un truc...

Il ne s'agit pas d'une expérimentation bien compliquée, mais simplement d'un essai afin d'amener des possibilités futures (jeu de pétanque par exemple...).
Des boules rebondissent sur un plan avec ombre et tout. Cliquez pour faire apparaître une nouvelle boule (attention, ça lague rapidement...).

balls papervision3D wow shadows

Pour les sources, clic droit sur l'exemple.

A bientôt

Télécharger les anciennes versions de Flash Player

Hello hello,

J'ai un peu galérer à les trouver, donc si vous en avez besoin, voici comment télécharger les anciennes versions de Flash Player :

Anciennes versions de Flash Player

Ca peut toujours être utile pour quelques tests...

A bientôt.

Mugsho , un widget qui vous déforme

Bonjour !

Ca fait maintenant presque cinq mois que je travaille chez Neoia, société toulousaine spécialisée, comme vous l'aurez deviné dans les RIA. Je vous invite à aller sur le site afin d'y trouver plus de renseignements.
Nous sortons aujourd'hui Mugsho, un widget pour vos sites ou blogs, permettant à vos visiteurs de se prendre en photo... Le petit plus, c'est que vous pouvez déformer votre tête grâce à une dizaine d'effets (renflement, stretch, miroir, ...)

Lire la suite

Flash Player 10 codename Astro prerelease

Bonjour

Un petit billet pour vous dire que Flash Player 10 est sorti en prerelease.

Je l'ai donc installé, et la démo sur le labs d'adobe nous montre les nouveautés. Je vous laisse voir par vous même.
Ce qui m'a le plus "impressionné" est la gestion de la 3D qui parait super fluide, comparé aux librairies Papervision, Sandy, etc... Il faudra voir par la suite ce qu'il est possible de faire.
Il est agréable aussi de voir la visualisation des textes sur deux colonnes, enfin on va pouvoir mettre en forme et page les textes, enfin j'espère.
Enfin, j'ai hâte de tâter Hydra et les filtres. Les possibilités, je pense, sont énormes.

Voili voilou, je vous conseille de visualiser les vidéos en bas de la page sur le labs.

A bientôt.


Je remercie Dhaya pour la news

Méthode simple pour communiquer entre composants d'un projet Flex

Bonjour,

Au fur à mesure des projets Flex, j'ai remarqué que la communication entre les composants de l'application, implémentée par l'envoi d'évenements, devenait peu à peu compliqué plus le projet devenait conséquent. Vous me direz d'utiliser dans ce cas là l'architecture MVC... En effet, pour les gros gros projets qui utilisent une grosse partie traitement cela est bien utile mais pour une application composée de quelques pages et composants il m'a fallu trouvé une autre solution.

Je ne garantie pas du tout que cette solution est la bonne, mais elle est bien pratique. Il s'agit d'utiliser un singleton en tant que notifieur. Pour ceux qui ne savent pas ce qu'est un singleton, il s'agit d'un objet instancié une seule fois mais pourtant disponible dans tous les autres objets souhaités (à peu près).

Lire la suite

Photoshop Express

Bonjour

Adobe a sorti aujourd'hui PhotoShop Express. Il s'agit d'un photoshop en ligne réalisé en Flex.

Pas mal d'outils, idéal pour des petites retouches. Le site est bien réalisé, un peu lent cependant, mais très propre et bien stylé.

Un truc que je trouve pas mal est la possibilité de retoucher des photos à partir de votre compte facebook ou bien picassa par exemple.

Amusez-vous !

Expressions régulières (RegEx)

Bonjour,
J'ai trouvé un lien intéressant en feuilletant le web. Il s'agit d'un résumé, tenant, sur une page, des "formules" utilisées par les expressions régulières.
Imprimez-le, accrochez le dans vos WC puis ça finira par rentrer... ou pas....
Et hop le lien !

Graphons les métros

Bonjour,

Je suis actuellement dans le métro, j'en ai encore pour une petite demi heure. Je suis assis à l'avant et je viens d'avoir une petite idée :
Le béton des tunnels du métro occupe une surface incroyable. Cette surface grise, est tout de ce qu'il y'a de plus morose et lugubre. Ainsi, pourquoi ne pas inviter les grapheurs afin de la décorer. En effet, on critique souvent ces jeunes (et moins jeunes !) de taguer n'importe où et n'importe comment...

graphons les métros

Lire la suite