Petite classe pour accéder facilement à des classes d’un swf chargé : BibliothequeItem
Salut à tous,
Pour commencer le mois de septembre, voici une classe que j’ai réalisée afin de me simplifier la vie lors de l’utilisation de bibliothèques externes.
Le cas habituel : j’ai un swf principal (Main), qui s’occupe de l’application, qui charge des données , xml, swf,… Pour qu’il soit léger, j’utilise en générale un autre swf qui contient les éléments (assets) visuels de mon application (hors mis les éléments comme les images d’une galerie par exemple que je préfère charger séparément pour des raisons de souplesse). Ainsi j’ai un swf généralement nommé assets qui contient ces éléments.
En générale, c’est ici que commence les ennuis.
Les classes contenues dans ce swf ne sont pas accessibles directement. C’est-Ã -dire que si dans le swf principal je fais :
-
var o:ClasseContenuDansAsset = new ClasseContenuDansAsset();
J’ai une belle erreur m’indiquant que la définition de classe ClasseContenuDansAsset n’existe pas.
Ceci est normal car le compilateur recherche la classe que nous voulons instancier dans l’ApplicationDomain de la classe Main.
Pour pouvoir créer l’occurrence comme nous le voulons il faut indiquer que nous cherchons une classe contenu dans un autre ApplicationDomain. Ce qui donne :
-
var o:ClasseContenuDansAsset = new (occurrenceChargéeDeAsset.loaderInfo.applicationDomain.getDefinition ("ClasseContenuDansAsset") as Class)();
Comme on peut facilement s’en rendre compte c’est léger comme écriture… Et comme nous devons faire ça pour toutes les occurrences que nous voulons créer, ça devient vite lourd!!
D’autant plus si nous voulons créer une occurrence dans une autre classe du projet que la classe Main ; la classe en question doit en plus avoir une référence à la classe Asset chargée…
L’idée pour résoudre ce problème est simple. Avoir une classe intermédiaire qui récupère l’objet ou la classe pour nous.
C’est là qu’intervient la classe BibliothequeItem.
Il suffit lorsque la classe d’assets est chargée de passer l’occurrence chargée à la propriété statique bibliotheque pour définir l’endroit où nous voulons chercher nos classes. Puis, d’utiliser au choix l’une des deux méthodes statiques suivantes pour instancier un objet :
-
var o:nomDeLaClasseAInstancier = BibliothequeItem.getInstance("nomDeLaClasseAInstancier");
qui retourne directement l’objet souhaité si le constructeur de la classe n’attend pas de paramètre (dans le cas où l’occurrence est un BitmapData il suffit de passer true comme deuxième paramètre).
ou
-
var o:nomDeLaClasse = new (BibliothequeItem.getClass("nomDeLaClasse"))([paramètres]);
.
Bon ben… C’est bon on a tout!
Cette méthode marche aussi dans les classes qui ne sont pas le Main. Il est important de noter tout de même, que le typage de variable est un peu compliqué puisque la classe n’est pas connue (importée) à l’origine. On lui préférera éventuellement une classe parente (toujours pour le typage).
Voici un exemple de classe Main qui charge un swf d’assets nommé assets.swf et qui le défini comme bibliothèque de référence. Il suffit en suite d’utiliser l’une des deux méthodes sus-nommées pour avoir l’objet que l’on souhaite :
-
package classes {
-
import com.inkProd.utils.BibliothequeItem;
-
import flash.display.Loader;
-
import flash.display.Sprite;
-
import flash.events.Event;
-
import flash.net.URLRequest;
-
/**
-
* …
-
* @author la pieuvre (Guillaume Le Souchu) / lesouchu@gmail.com
-
*/
-
[SWF (width = "960", height = "700", frameRate = "50", backgroundColor = "0xffffff", pageTitle = "Main")]
-
public class Main extends Sprite{
-
-
/*
-
//
-
///////////////////////////////////////////////////////////////////
-
///////////////////////////////////////////////// PROPRIETES
-
///////////////////////////////////////////////////////////////////
-
//
-
*/
-
-
//////////////////////////////////////////////////////////////////
-
// PROTECTED
-
//
-
protected var _assetLoader:Loader = new Loader();
-
-
/*
-
//
-
//////////////////////////////////////////////////////////////////
-
///////////////////////////////////////////// CONSTRUCTEUR
-
//////////////////////////////////////////////////////////////////
-
//
-
*/
-
public function Main() {
-
_initAssetLoader();
-
}
-
/*
-
//
-
//////////////////////////////////////////////////////////////////
-
/////////////////////////////////////////////// METHODES
-
//////////////////////////////////////////////////////////////////
-
//
-
*/
-
-
//////////////////////////////////////////////////////////////////
-
// PROTECTED
-
//
-
protected function _initAssetLoader():void {
-
_assetLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, _assetLoadCompHandeler);
-
_assetLoader.load(new URLRequest("assets.swf"));
-
}
-
////////////////////////////////////////////////////////
-
// ECOUTEUR
-
//
-
protected function _assetLoadCompHandeler(e:Event):void {
-
BibliothequeItem.bibliotheque = _assetLoader.content
-
}
-
}
-
}
Voilà , à bientôt pour d’autres sources. ;)
There are 6 Comments to "Petite classe pour accéder facilement à des classes d’un swf chargé : BibliothequeItem"
Et bien félicitation !!!
Je suis heureux de constater qu’il existe des gens comme toi, qui se creuse pour essayer de comprendre les mécanismes profonds de AS3 et surtout qui ne jette pas l’éponge si facilement quand par exemple, tout le monde Déclare « on ne sait pas accéder à une classe d’un SWF chargé dynamiquement. via un loader »..
Cependant, ton code a sans doute été mal retranscrit, car il n’a pas fonctionné chez moi, j’ai du passer par le content pour qu’il fonctionne. le voici:
var cdj:MovieClip = new (loader.content.loaderInfo.applicationDomain.getDefinition("Cdj1000MK3"));
Néanmoins, ça contredit un truc que j’ai écris sur mon blog.. Je vais donc corriger cela et partager ta trouvaille ;)
Quand à ta classe, elle fonctionne, j’ai dû juste ajouter quelques typage, sinon, le compilo donnait des warnings.
Ta méthode est super, mais elle est pratique pour ceux qui codent dans Flash, pas pour ceux qui sont sous FD3, FDT ou Eclipse, car on ‘a absolument aucune autocomplétion puisqu’évaluée qu’au runtime.
Je t’invite à consulter mon blog, post RSL et me dire ce que tu en penses.. ;)
Par la suite, je serai ravi de te conpter parmis mes amis, car on pourra sans doute mieux évoluer à plusieurs..
Bravo pour ton taf.
Alain.
Salut et merci pour ton commentaire. :D
En fait pour ce qui est de
var o:ClasseContenuDansAsset = new (occurrenceChargéeDeAsset.loaderInfo.applicationDomain.getDefinition ("ClasseContenuDansAsset") as Class)();occurrenceChargéeDeAsset fait déjà référence à loader.content puisque, par définition, le loader est l’objet qui charge en non celui qui est chargé… mais il est vrai que ce n’est peut-être pas très clair :)
En ce qui concerne l’auto-complétion que j’utilise également puisque je travaille (malgré tout) avec flashdévelop. pour la plus part des éléments c’est suffisant. Par exemple, l’essentiel de ma classe d’asset contient des png importés avec la méthode suivante :
la classe retournée est du type BitmapAsset. On a donc toutes les complétions que l’on veut en typant sa variable comme ceci. Cependant pour les classes étendant Sprite ou MovieClip avec des fonctionnalités supplémentaires. Soit on importe la classe quand même dans l’entête soit on se contente de l’auto-complétion de la classe parent à savoir Sprite ou MovieClip.
Voilà j’espère que ça répond à tes interrogations sur le sujet.
…Cependant je suis curieux de savoir qu’elle avertissement tu as eu à la compilation et quelles classes manquées.
À bientôt sur ton blog ou le mien. ;)
Guillaume.
Merci!
Les warnings étaient des manques de déclaration de Type de fonctions et le param pIsDitmapData (:Boolean) Bêtises quoi..
Ok pour la variable qui référence déjà le content ;-)
++ ;)
Alain.
Ok merci!! c’est mis à jour :)
Salut :)
C’est avec une interface qu’il faut typer la variable dans le swf Main ! ;-) A condition bien sûr que les classes externes l’implémentent.
Comme ça, pas besoin de connaître la classe réelle, on a la completion et on ne se rajoute quasiment aucun poids dans la compilation du Main (à condition d’éviter de citer dans l’interface des classes des SWF externes -préférer là -aussi des interfaces-).
++ Monsieur Pieuvre. :)
Welcome mister Dada.
Effectivement, une interface serai la meilleure chose, mais clairement on ne les utilise pas tous les jours (enfin ça dépend de la taille du projet). :)