It’s been a long-time without a post. Part of the reason for that has been starting work at a new job (which involves a commute), and part has been that as part of my new job, I was actually encouraged to spend time playing World of Warcraft. To me, that’s like taking a crowbar to Pandora’s Box and having a peek inside. I learned quite a lot, but have also played just a few too many Warsong Gulches.
Back to work, and I was doing a little prototyping this evening, when I came across a familiar problem: In AS3
we can use
1
2
3
4
|
[Embed(source=
"asset.swf"
, symbol=
"symbol"
)]
private
var
symbolClass:Class;
var
symbol:MovieClip =
new
symbolClass();
|
to embed a symbol from an art SWF
in what is probably a code-built SWF
. That’s great, but what if you want to embed an entire SWF
?
1
2
3
4
|
[Embed(source=
"asset.swf"
)]
private
var
assetClass:Class;
var
asset:MovieClip =
new
assetClass();
|
looks like it should do the trick, but you can’t access any of the information within the asset. That’s a real pain, the reason for which is pretty convoluted. I remembered working around this problem in the past, and happily managed to unearth a long-forgotten treasure in my codebase, which I thought I’d share (having rapidly refactored it to use as3-signals, naturally).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
package
com.alecmce.util
{
import
org.osflash.signals.Signal;
import
mx.core.MovieClipAsset;
import
flash.display.Loader;
import
flash.display.LoaderInfo;
import
flash.display.MovieClip;
import
flash.events.Event;
public
class
UnpackEmbed
{
private
var
_ready:Signal;
private
var
_asset:MovieClipAsset;
private
var
_content:MovieClip;
public
function
UnpackEmbed(assetClass:Class)
{
_asset =
new
assetClass();
_ready =
new
Signal(UnpackEmbed);
var
loader:Loader = Loader(_asset.getChildAt(
0
));
var
info:LoaderInfo = loader.contentLoaderInfo;
info.addEventListener(Event.COMPLETE, onLoadComplete);
}
private
function
onLoadComplete(event:Event):
void
{
var
info:LoaderInfo = LoaderInfo(event.target);
info.removeEventListener(Event.COMPLETE, onLoadComplete);
_content = MovieClip(info.loader.content);
_ready.dispatch(
this
);
}
public
function
get
content():MovieClip
{
return
_content;
}
public
function
get
ready():Signal
{
return
_ready;
}
public
function
get
asset():MovieClipAsset
{
return
_asset;
}
}
}
|
When you embed a SWF in this way then instantiate it, Flash somehow conspires to create a MovieClipAsset
with a Loader
inside, which will be ‘loading’ the already-embedded content. The content is not available immediately (it may be sometimes, I have encountered cases where it was not), so you have to wait for an Event.COMPLETE
to be fired before you can access it. This class exposes a signal that informs you when the content is ready. It could probably be more rigorous, such as including an isComplete
flag, but it serves my purposes, when used in the following manner:
1
2
3
4
5
6
7
8
9
10
|
[Embed(source=
"asset.swf"
)]
private
var
assetClass:Class;
asset =
new
UnpackEmbed(assetClass);
asset.ready.addOnce(onAssetReady);
private
function
onAssetReady(asset:UnpackEmbed):
void
{
// now we can access the asset.content!
}
|