Everything [Embed]

| | Comments (2) | TrackBacks (0)
This article should provide you with all the ammo you need when using the Embed meta tag. It is a vital part of AS3 and should greatly enhance the structure of your projects. Hopefully this article will show the benefits of structuring your projects in this way.

The designer developer workflow is a constant sorrow for may folks but it doesn't have to be. Like any relationship communication is key but so is planning. More often than not these days, design continues even though development may have started. The mish-mash of the creative and tech workflow is an interesting one, one we can't seem to get right nor move away from. Flash in particular seem to be challenging as its roots are firmly anchored in creative and design. But we can try.

We can however try to minimise any problems in this workflow by using best practices and structured code. By using the Embed tag we can do exactly this. It is equivalent to the FLA library, but an invisible library if you will. Even though it is practically the same as the Flash IDE library, it has way more advantages and possibilities.  I will assume you are using either Eclipse and FDT or Flex Builder as your chosen development environment.

Flash CS3

The Flash authoring will throw "TypeError: Error #1007: Instantiation attempted on a non-constructor." because it doesn't support the Embed meta tag, it ignores it actually. You can only use the Embed tag in Flex or compiling with the Flex SDK. If you think about it there is no reason why you would need to do this. But there are rumuors that this will be included in future versions of the Flash IDE.

Understanding embed source paths

Using the Embed meta tag within a class assumes the root to be the class location, i.e. the class that is embedding the file's location. Embed requires you to point to the external file using a relative path. Logical but a bit strange as you might end up with something like "../../../../../../assets/library.swf" to embed a symbol in a specific class that is nested deep in a specific package. As this is relative, you can always just start with a "/" to set the start of your find-where-the-location-of-asset-is-mission. This way we end up with  "/../assets/library.swf". Starting with the "/" first refers to the root of your class packages. In the example below this would be "com". So to get to the "assets" folder we have to move one level up. This rule is ever present and works for all types of Embed. The Embed directive in Flex works in exactly the same way.

embed_01.gif

Images

Below is a very straight forward example of embedding an image and adding it to the stage.

package com.wezside.core 
{
	import flash.display.Sprite;	
		
	/**
	 * @author Wesley.Swanepoel
	 */
	public class Main extends Sprite
	{

		[ Embed(source="/../assets/Mona_Lisa.jpg") ]
		private var Square:Class;
			
		public function Main() 
		{
			addChild( new Square() );
		}
			
	}
}

Fonts

There are a few things to take note of when embedding fonts:
  • source - The location of the file, types *.ttf, *.ttc and *.otf are supported
  • fontWeight - Should the font be a specific weight, i.e. bold then that should be declared or the compiler will throw an error
  • fontFamily - The name given to the font to be used in the TextFormat
  • fontName - Same as fontFamily

..
[ Embed( source="/../assets/fonts/American Typewriter.ttf", 
		 fontFamily="AmericanT", 
		 mimeType="application/x-font-truetype" ) ]
private var AmericanT:String;	
..
	var format:TextFormat = new TextFormat();
	format.font = "Helvetica";
..

It is not necessary to embed the entire font. You can specify which glyphs to add for each font. Just add the unicodeRange='U+0020-U+002F,U+0030-U+0039,U+003A-U+0040' of the glyphs you need. If you don't know what to include see the ranges on the official Unicode site.


MimeType declarations

With any embed you can explicitly specify the mimeType of the file being added. With fonts we will specify mimeType="application/x-font" to give the compiler a heads up on what format will be included. You do not have to include the mimeType as the compiler will attempt to do so.

By far the most exciting mimeType supported is "application/octet-stream". This type specifically is a binary file. Therefore we have access to the bytes using ByteArray. What is this useful for you may ask? you will now be able to define your own file and format and include that into your SWF. If we know enough about what is under hood of a specific file, we could write our own parser or for some files encoder/decoder. For example, if you knew the byte structure of a Word Doc, you can embed the file using this mimeType and then access the Bytes through ByteArray, parse this file with your custom parser, encode it using the JPEGEncoding class to convert it to an image and get sued by Microsoft for millions. But seriously, some file types (*.wav for example) use a standard and the details are available online. All you need is a bit of brain muscle and spare time and there you go.


AssetManager

So you might think that this is really cool stuff and it is. But it can become a bit of a nightmare to maintain. Allow me to explain. Imagine you have quite a few classes that all embed some assets you want to use throughout your project. You might find yourself in a situation very similar to finding MovieClips in the old days on nested timelines.

A better solution would be to have all your embedded assets in one location as you would with a library in the Flash IDE. So why make this any different? The AssetManager has popped up a few times over the net and it makes absolute sense. One class, one location that has all the embed options. I have this as a singleton but it doesn't have to be. The only requirement for use of the AssetManager is to instantiate it. We want the compiler to know that it must include this class when compiling the SWF.

 
AssetManager.as
package com.wezside.lib 
{
	import flash.utils.describeType;
	import flash.utils.getDefinitionByName;

	/**
	 * @author Wesley.Swanepoel
	 * @version .001
	 */
	public class AssetManager
	{
		
		[ Embed( source="/../assets/fonts/American Typewriter.ttf", fontName="AmericanT", mimeType="application/x-font-truetype" ) ]
	 	public static const FONT_AMERICA_T:String;		

		[ Embed( source="/../assets/library.swf", symbol="Square") ];
		private var Square:Class;

		[ Embed (source="/../assets/Mona_Lisa.jpg") ]
		private var MonaLisa:Class;

		private static var instance:AssetManager;
		
		public static function getInstance():AssetManager 
		{
			if (instance == null)
				instance = new AssetManager();
			return instance;
		}
		
		public function getAssetByName( name:String ):*
		{
			var className:String = describeType( this ).@name.toXMLString();
			var fullname:String = className + "_" + name;
			var ref:Object = getDefinitionByName( fullname );
			return new ref();
		}		
		
	}
}
Main.as
package com.wezside.core 
{
	import flash.display.Sprite;
	import flash.text.TextField;
	import flash.text.TextFormat;
	
	import com.wezside.lib.AssetManager;		

	/**
	 * @author Wesley.Swanepoel
	 */
	public class Main extends Sprite
	{
		
		public function Main() 
		{
			// Initialise the AssetManager to let compiler include our assets in the compiled SWF
			var am:AssetManager = AssetManager.getInstance();
			
			// Create the TextFormat to specify our font
			var format:TextFormat = new TextFormat();
			format.font = "AmericanT";
			format.size = 26;
			
			// Create TextField
			var field:TextField = new TextField();
			field.text = "AssetManager";
			field.embedFonts = true;
			field.width = 200;
			field.setTextFormat(format);
			
			// Add assets to stage			
			addChild( am.getAssetByName("MonaLisa") );
			addChild( field );
		}
		
	}
}
		

You can download the source for the example project here »


Compiler Errors

These errors are common when using the Embed meta tag. Even though my guess is there are multiple problems that use the same error message, these are some common messages you may find along the way.

Error: Embed is only supported on classes and member variables

Remove the ";" after the [Embed] tag.

Error: unable to resolve '/../../assets/fonts/American Typewriter.ttf' for transcoding
Your path to the asset is wrong.

Error: exception during transcoding: Font for alias 'Helvetica' with plain weight and style was not found
The font you are trying to embed has a weight other than what you have defined. If you have omitted the "font-weight" value then default "normal" will be used.


Resources


0 TrackBacks

Listed below are links to blogs that reference this entry: Everything [Embed].

TrackBack URL for this entry: http://www.wezside.co.za/cgi-bin/mt/mt-tb.cgi/34

2 Comments

By bunnyhero on October 18, 2008 5:56 AM

i hope [Embed] comes to the Flash IDE. you say "If you think about it there is no reason why you would need to do this", but you actually provide an example of why you might need to do this in flash-- namely, the application/octet-stream mimetype with any arbitrary binary file. this cannot be done in flash with the symbol library, as far as i know.

By Killian on April 24, 2009 5:22 PM

Does embed work with .flv?

Leave a comment


Type the characters you see in the picture above.