Flex Preloader without Flash CS - apache-flex

I have been digging for custom Flex preloaders and they all seem to rely on the same template:An SWC is created with Flash CS5 and then used by Flash Builder using the "preloader" application property.
I don't own Flash CS, and it feels that Flash builder should be able to do the trick.
I created a Library Project in Flash Builder with the following bare bones code:
package loader
{
import flash.display.DisplayObject;
import flash.events.Event;
import flash.utils.getTimer;
import mx.events.RSLEvent;
import mx.preloaders.DownloadProgressBar;
import mx.preloaders.SparkDownloadProgressBar;
public class Preloader extends SparkDownloadProgressBar
{
[Embed(source="loaderlogo.png")] public var logoClass:Class;
private var _displayStartCount:uint = 0;
private var _initProgressCount:uint = 0;
private var _downloadComplete:Boolean = false;
private var _showingDisplay:Boolean = false;
private var _startTime:int;
// private var preloaderDisplay:PreloaderDisplay;
private var rslBaseText:String = "loading: ";
public function Preloader()
{
super();
}
/**
* Event listener for the <code>FlexEvent.INIT_COMPLETE</code> event.
* NOTE: This event can be commented out to stop preloader from completing during testing
*/
override protected function initCompleteHandler(event:Event):void
{
dispatchEvent(new Event(Event.COMPLETE));
}
/**
* Creates the subcomponents of the display.
*/
override protected function createChildren():void
{
var img:DisplayObject = new logoClass();
img.x = Math.round( ( stageWidth - img.width) / 2);
img.y = Math.round( ( stageHeight - img.height) / 2);
addChild( img);
var dpb:DownloadProgressBar = new DownloadProgressBar();
dpb.x = img.x + 100;
dpb.y = img.x + 100;
dpb.width = 170;
dpb.height = 20;
addChild( dpb);
}
/**
* Event listener for the <code>RSLEvent.RSL_PROGRESS</code> event.
**/
override protected function rslProgressHandler(evt:RSLEvent):void {
if (evt.rslIndex && evt.rslTotal) {
//create text to track the RSLs being loaded
rslBaseText = "loading RSL " + evt.rslIndex + " of " + evt.rslTotal + ": ";
}
}
/**
* indicate download progress.
*/
override protected function setDownloadProgress(completed:Number, total:Number):void {
}
/**
* Updates the inner portion of the download progress bar to
* indicate initialization progress.
*/
override protected function setInitProgress(completed:Number, total:Number):void {
}
/**
* Event listener for the <code>FlexEvent.INIT_PROGRESS</code> event.
* This implementation updates the progress bar
* each time the event is dispatched.
*/
override protected function initProgressHandler(event:Event):void {
var elapsedTime:int = getTimer() - _startTime;
_initProgressCount++;
if (!_showingDisplay && showDisplayForInit(elapsedTime, _initProgressCount)) {
_displayStartCount = _initProgressCount;
show();
// If we are showing the progress for the first time here, we need to call setDownloadProgress() once to set the progress bar background.
setDownloadProgress(100, 100);
}
if (_showingDisplay) {
// if show() did not actually show because of SWFObject bug then we may need to set the download bar background here
if (!_downloadComplete) {
setDownloadProgress(100, 100);
}
setInitProgress(_initProgressCount, initProgressTotal);
}
}
private function show():void
{
// swfobject reports 0 sometimes at startup
// if we get zero, wait and try on next attempt
if (stageWidth == 0 && stageHeight == 0)
{
try
{
stageWidth = stage.stageWidth;
stageHeight = stage.stageHeight
}
catch (e:Error)
{
stageWidth = loaderInfo.width;
stageHeight = loaderInfo.height;
}
if (stageWidth == 0 && stageHeight == 0)
return;
}
_showingDisplay = true;
createChildren();
}
}
}
For short, it's loading a logo and a progress bar
It displays a preloader, but really late in the loading process. As if it was being loaded after Flex.
Do I need to compile this in CS5 to completely avoid use of MX/Spark?

You shouldn't use any components in preloader. Try to remove you imports (Ctrl+Shift+O):
import mx.controls.Image;
import spark.components.Label;
Use TextField and Loader instead if needed. I'm not sure about DownloadProgressBar component.
Also don't use create children in preloader. Here is one working sample:
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import mx.core.mx_internal;
import mx.preloaders.SparkDownloadProgressBar;
use namespace mx_internal;
public class Preloader extends SparkDownloadProgressBar {
private var preloaderLogo : MovieClip;
private var loadingText : TextField;
private var loadingProgress : TextField;
private var _initProgressCount : uint = 0;
private var textFormat : TextFormat = new TextFormat("Verdana", 16, 0x666666, true);
public function Preloader() {
super();
textFormat.align = "center";
}
override public function set preloader(value : Sprite) : void {
super.preloader = value;
if (!preloaderLogo) {
preloaderLogo = new Assets.PRELOADER_LOGO; // kakaranet logo
var startX : Number = Math.round((stageWidth - preloaderLogo.width) / 2);
var startY : Number = Math.round(stageHeight / 2 - preloaderLogo.height) - 100;
preloaderLogo.x = startX;
preloaderLogo.y = startY;
loadingText = new TextField();
loadingProgress = new TextField();
loadingText.width = stageWidth;//to allow center align
loadingProgress.width = stageWidth;
loadingText.text = "Loading...";
loadingText.y = preloaderLogo.y + preloaderLogo.height + 20;
loadingProgress.text = "0%";
loadingProgress.y = loadingText.y + loadingText.textHeight + 10;
addChild(preloaderLogo);
addChild(loadingText);
addChild(loadingProgress);
loadingText.setTextFormat(textFormat);
loadingProgress.setTextFormat(textFormat);
}
}
override protected function progressHandler(event : ProgressEvent) : void {
super.progressHandler(event);
if (loadingProgress) {
loadingProgress.text = Math.floor(event.bytesLoaded / event.bytesTotal * 100) + "%";
loadingProgress.setTextFormat(textFormat);
}
}
override protected function completeHandler(event : Event) : void {
loadingText.text = "Ready!";
loadingText.setTextFormat(textFormat);
preloaderLogo.stop();
}
override protected function initProgressHandler(event : Event) : void {
super.initProgressHandler(event);
//similar to super
_initProgressCount++;
if (loadingProgress) {
loadingProgress.text = "100% / " + Math.floor(_initProgressCount / initProgressTotal * 100) + "%";
loadingProgress.setTextFormat(textFormat);
}
}
}
}

Related

Starling embed bitmap reference error

I have the following code in the Game.as:
package
{
import flash.display.Bitmap;
import starling.display.Image;
import starling.display.Sprite;
import starling.events.Event;
import starling.textures.Texture;
import starling.utils.deg2rad;
public class Game extends Sprite
{
private const NUM_SAUSAGES: uint = 400;
private var sausagesVector: Vector.<Image> = new Vector.<Image>(NUM_SAUSAGES, true);
[Embed(source = "../media/textures/sausage.png")]
private static const Sausage: Class;
public function Game()
{
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded(e: Event): void
{
var sausageBitmap: Bitmap = new Sausage();
var texture: Texture = Texture.fromBitmap(sausageBitmap);
for (var i: int = 0; i < NUM_SAUSAGES; ++i)
{
var image: Image = new Image(texture);
image.alpha = Math.random();
image.x = Math.random() * stage.stageWidth;
image.y = Math.random() * stage.stageHeight;
image.rotation = deg2rad(Math.random() * 360);
addChild(image);
sausagesVector[i] = image;
}
}
}
}
But when I run the code it gives me the following error:
ReferenceError: Error #1065: Variable Game_Sausage is not defined.
What is the problem with the code because I have no idea?
I don't know the notation but I would hazard a guess that:
private static const Sausage: Class;
is never assigned, but defined as const. The [Embed] might not be finding the file?
a quick google found:
http://www.flexer.info/2009/05/01/getdefinitionbyname-error-variable-is-not-defined/
which might or might not be relevant

Flex popup manager, mousedown outside of the popup removes the popup

If you create a popup via:
PopUpManager.addPopUp( popup, this, false );
PopUpManager.bringToFront( popup );
It will create a popup and bring it on top of any other visual piece. I have one problem though. This 'popup' needs to stay up even when the user interacts with the background.
I would use modal, but I need the ability to interact with the back. Any way to tell the popup manager not to remove the popup when the user clicks off of it?
Thanks!
here's a helper class which would help you (tested only in Flex 4, but probably could be changed for Flex 3 too):
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.MouseEvent;
import mx.core.mx_internal;
import mx.managers.ISystemManager;
import mx.managers.systemClasses.ActiveWindowManager;
use namespace mx_internal;
public class PopupHelper
{
private var popup : DisplayObject;
private var systemManager : ISystemManager;
public function PopupHelper(popup : DisplayObject, systemManager : ISystemManager) : void
{
this.popup = popup;
this.systemManager = systemManager;
}
public function forceToFront() : void
{
systemManager.addEventListener(MouseEvent.MOUSE_DOWN, onSystemMouseDown);
popup.addEventListener(Event.REMOVED_FROM_STAGE, onPopupRemoved)
}
private function onSystemMouseDown(e : MouseEvent) : void
{
bringToFront(popup);
}
private function onPopupRemoved(e : Event) : void
{
popup.removeEventListener(Event.REMOVED, onPopupRemoved);
systemManager.removeEventListener(MouseEvent.MOUSE_DOWN, onSystemMouseDown);
}
private function bringToFront(popup : DisplayObject) : void
{
var windowManager : ActiveWindowManager = systemManager.getImplementation("mx.managers::IActiveWindowManager") as ActiveWindowManager;
var index : int = systemManager.getChildIndex(popup);
var newIndex : int = index;
var n : int = windowManager.forms.length;
for (var j : int = 0; j < n; j++)
{
var f : DisplayObject = windowManager.forms[j];
if (systemManager.contains(f))
if (systemManager.getChildIndex(f) > index)
newIndex = Math.max(systemManager.getChildIndex(f), newIndex);
}
if (newIndex > index)
{
systemManager.setChildIndex(popup, newIndex);
}
}
}
Here's a test example:
import helperClasses.PopupHelper;
import mx.managers.PopUpManager;
import spark.components.TitleWindow;
public function showPopup() : void
{
var popup1 : TitleWindow = new TitleWindow();
popup1.title = "Popup 1";
new PopupHelper(popup1, systemManager).forceToFront();
var popup2 : TitleWindow = new TitleWindow();
popup2.title = "Popup 2";
PopUpManager.addPopUp(popup1, this, false);
PopUpManager.addPopUp(popup2, this, false);
PopUpManager.bringToFront(popup1);
popup1.x = 20;
popup1.y = 20;
}

large image loading problem

I had tired loading an image form a url below is my sample code , when tried to load a large image which is greater than 8191 pixel in width or height the Event.COMPLETE is not dispatched , i am aware of the flash player 10 BitmapData limit ,so cant we load an image greater than this 8191 pixel limit ?is there any workaround for this Or any other method you suggest in doing ?
private function loadImage(url:String):void
{
var request:URLRequest = new URLRequest(url);
var imageLoader:Loader = new Loader();
var context:LoaderContext;
context = new LoaderContext();
context.checkPolicyFile = true;
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, image_completeHandler);
imageLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
imageLoader.load(request,context);
}
private function image_completeHandler(event:Event):void
{
trace(" Image load Complete");
}
private function ioErrorHandler(event:IOErrorEvent):void
{
trace("ioErrorHandler: " + event);
}
I would recommend that you split up the images. If you need Flash to handle the images as one (moving, scaling) I would write a holder-class that adds the image pieces as children of the itself.
I added some code and a link to a test below. Look at the code in action here. (wait for the SWF to load).
//TestClass
package
{
import com.kazumakzak.display.TileImage;
import flash.display.Sprite;
import flash.events.Event;
public class TestBigImage extends Sprite
{
[Embed(source="assets/piece.png")]
private var imageClass : Class;
private var _image : TileImage;
private var _counter : Number = 0;
public function TestBigImage()
{
// create image with tile size 640x480
_image = new TileImage(640, 480);
// add tiles at positions
_image.addTile(new imageClass(), 1, 1);
_image.addTile(new imageClass(), 1, 2);
_image.addTile(new imageClass(), 2, 1);
_image.addTile(new imageClass(), 2, 2);
_image.addTile(new imageClass(), 3, 1);
_image.addTile(new imageClass(), 3, 2);
// add to display list
addChild(_image);
addEventListener(Event.ENTER_FRAME, render);
}
private function render(event : Event) : void
{
_counter += 0.05;
_image.x = -640 + Math.cos(_counter) * 640
}
}
}
//TileImage.as
package com.kazumakzak.display
{
import flash.display.Bitmap;
import flash.display.Sprite;
public class TileImage extends Sprite
{
private var _tileWidth : int;
private var _tileHeight : int;
public function TileImage(tileWidth : int, tileHeight : Number)
{
_tileWidth = tileWidth;
_tileHeight = tileHeight;
}
public function addTile(source : Bitmap, tileX : int, tileY : int) : void
{
source.x = (tileX-1) * _tileWidth;
source.y = (tileY-1) * _tileHeight;
addChild(source);
}
}
}

Flex actionscript extending DateChooser, events in calendar

ExtendedDateChooser class is great solution for simple event calendar used in my flex project. You can find it if google for "Adding-Calendar-Event-Entries-to-the-Flex-DateChooser-Component"
with a link of updated solution in comments of the post. I posted files below.
Problem in that calendar is text events are missing when month is changed.
Is there updateCompleted event in Actionscript just like in dateChooser flex component? Like in:
<mx:DateChooser id="dc" updateCompleted="goThroughDateChooserCalendarLayoutAndSetEventsInCalendarAgain()"</mx>
When scroll event is added, which is
available in Actionscript, it gets
dispatched but after
updateDisplayList() is fired, so
didn't manage to answer, why are
calendar events erased?
Any suggestions, what to add in code, maybe override some function?
ExtendedDateChooserClass.mxml
<?xml version='1.0' encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:mycomp="cyberslingers.controls.*"
layout="absolute"
creationComplete="init()">
<mx:Script>
<![CDATA[
import cyberslingers.controls.ExtendedDateChooser;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
import mx.controls.Alert;
public var mycal:ExtendedDateChooser = new ExtendedDateChooser();
// collection to hold date, data and label
[Bindable]
public var dateCollection:XMLList = new XMLList();
private function init():void
{
eventList.send();
}
private function readCollection(event:ResultEvent):void
{
dateCollection = event.result.calendarevent;
//Position and size the calendar
mycal.width = 400;
mycal.height = 400;
//Add the data from the XML file to the calendar
mycal.dateCollection = dateCollection;
//Add the calendar to the canvas
this.addChild(mycal);
}
private function readFaultHandler(event:FaultEvent):void
{
Alert.show(event.fault.message, "Could not load data");
}
]]>
</mx:Script>
<mx:HTTPService id="eventList"
url="data.xml"
resultFormat="e4x"
result="readCollection(event);"
fault="readFaultHandler(event);"/>
</mx:Application>
ExtendedDateChooser.as
package cyberslingers.controls
{
import flash.events.Event;
import flash.events.TextEvent;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.controls.CalendarLayout;
import mx.controls.DateChooser;
import mx.core.UITextField;
import mx.events.FlexEvent;
public class ExtendedDateChooser extends DateChooser
{
public function ExtendedDateChooser()
{
super();
this.addEventListener(TextEvent.LINK, linkHandler);
this.addEventListener(FlexEvent.CREATION_COMPLETE, addEvents);
}
//datasource
public var dateCollection:XMLList = new XMLList();
//--------------------------------------
// Add events
//--------------------------------------
/**
* Loop through calendar control and add event links
* #param e
*/
private function addEvents(e:Event):void
{
// loop through all the calendar children
for(var i:uint = 0; i < this.numChildren; i++)
{
var calendarObj:Object = this.getChildAt(i);
// find the CalendarLayout object
if(calendarObj.hasOwnProperty("className"))
{
if(calendarObj.className == "CalendarLayout")
{
var cal:CalendarLayout = CalendarLayout(calendarObj);
// loop through all the CalendarLayout children
for(var j:uint = 0; j < cal.numChildren; j++)
{
var dateLabel:Object = cal.getChildAt(j);
// find all UITextFields
if(dateLabel.hasOwnProperty("text"))
{
var day:UITextField = UITextField(dateLabel);
var dayHTML:String = day.text;
day.selectable = true;
day.wordWrap = true;
day.multiline = true;
day.styleName = "EventLabel";
//TODO: passing date as string is not ideal, tough to validate
//Make sure to add one to month since it is zero based
var eventArray:Array = dateHelper((this.displayedMonth+1) + "/" + dateLabel.text + "/" + this.displayedYear);
if(eventArray.length > 0)
{
for(var k:uint = 0; k < eventArray.length; k++)
{
dayHTML += "<br><A HREF='event:" + eventArray[k].data + "' TARGET=''>" + eventArray[k].label + "</A>";
}
day.htmlText = dayHTML;
}
}
}
}
}
}
}
//--------------------------------------
// Events
//--------------------------------------
/**
* Handle clicking text link
* #param e
*/
private function linkHandler(event:TextEvent):void
{
// What do we want to do when user clicks an entry?
Alert.show("selected: " + event.text);
}
//--------------------------------------
// Helpers
//--------------------------------------
/**
* Build array of events for current date
* #param string - current date
*
*/
private function dateHelper(renderedDate:String):Array
{
var result:Array = new Array();
for(var i:uint = 0; i < dateCollection.length(); i++)
{
if(dateCollection[i].date == renderedDate)
{
result.push(dateCollection[i]);
}
}
return result;
}
}
}
data.xml
<?xml version="1.0" encoding="utf-8"?>
<rss>
<calendarevent>
<date>8/22/2009</date>
<data>This is a test 1</data>
<label>Stephens Test 1</label>
</calendarevent>
<calendarevent>
<date>8/23/2009</date>
<data>This is a test 2</data>
<label>Stephens Test 2</label>
</calendarevent>
</rss>
Just Change the FlexEvent.CREATION_COMPLETE in the ExtendedDateChooser.as to FlexEvent.UPDATE_COMPLETE
That should do.

Custom Preloader in Flex 4?

Has anyone successfully implemented a custom preloader in Flex 4? In my experience, when I specify a custom preloader using the preloader="com.foo.MyPreloader" in the Application tag, the preloader does not display until the SWF is completely downloaded, defeating the purpose of the preloader! Perhaps this is a bug in the still-beta Flex 4 framework?
I've been using this example in many Flex3 projects. It's still working with Flex4 sdk:
I can remember where I get it from. And you are right when you say it's important that this script is NOT referencing anything...
<s:Application tag ... preloader="com.YYY.XXX.shell.view.CustomPreloader"
CustomPreloader
package com.YYY.XXX.shell.view
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
import mx.events.FlexEvent;
import mx.preloaders.DownloadProgressBar;
public final class CustomPreloader
extends DownloadProgressBar
{
public var loader : LoadScreen;
private var _timer : Timer;
public function CustomPreloader()
{
super();
}
override public function initialize() : void
{
super.initialize();
this.loader = new LoadScreen();
this.addChild(this.loader);
this._timer = new Timer(1);
this._timer.addEventListener(TimerEvent.TIMER, handleTimerTick);
this._timer.start();
}
override public function set preloader(preloader : Sprite):void
{
preloader.addEventListener(ProgressEvent.PROGRESS, SWFDownLoadScreen);
preloader.addEventListener(Event.COMPLETE, SWFDownloadComplete);
preloader.addEventListener(FlexEvent.INIT_PROGRESS, FlexInitProgress);
preloader.addEventListener(FlexEvent.INIT_COMPLETE, FlexInitComplete);
}
private function SWFDownLoadScreen(event : ProgressEvent) : void
{
var prog : Number = event.bytesLoaded / event.bytesTotal * 100;
if (this.loader)
{
this.loader.progress = prog;
}
}
private function handleTimerTick(event : TimerEvent) : void
{
this.stage.addChild(this);
this.loader.x = (this.stageWidth - this.loader.width) / 2;
this.loader.y = (this.stageHeight - this.loader.height) / 2;
this.loader.refresh();
}
private function SWFDownloadComplete(event : Event) : void {}
private function FlexInitProgress(event : Event) : void {}
private function FlexInitComplete(event : Event) : void
{
this.loader.ready = true;
this._timer.stop();
this.dispatchEvent(new Event(Event.COMPLETE));
}
override protected function showDisplayForInit(elapsedTime:int, count:int):Boolean
{
return true;
}
override protected function showDisplayForDownloading(elapsedTime:int,
event:ProgressEvent):Boolean
{
return true;
}
}
}
LoadScreen
package com.YYY.XXX.shell.view
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.Sprite;
import flash.utils.ByteArray;
import mx.graphics.codec.PNGEncoder;
public class LoadScreen extends Loader {
//~ Settings ----------------------------------------------------------
private static var _BarWidth : int = 153; // Progress bar width
private static var _BarHeight : int = 12; // Progress bar height
private static var _LogoHeight : int = 153; // Logo picture height
private static var _LogoWidth : int = 68; // Logo picture width
private static var _Padding : int = 5; // Spacing between logo and progress bar
private static var _LeftMargin : int = 0; // Left Margin
private static var _RightMargin : int = 0; // Right Margin
private static var _TopMargin : int = 1; // Top Margin
private static var _BottomMargin : int = 1; // Bottom Margin
private static var _BarBackground : uint = 0xFFFFFF; // background of progress bar
private static var _BarOuterBorder : uint = 0x737373; // color of outer border
private static var _BarColor : uint = 0x6F9FD5; // color of prog bar
private static var _BarInnerColor : uint = 0xFFFFFF; // inner color of prog bar
//~ Instance Attributes -----------------------------------------------
[Embed(source="/asset/embed/img/XXX.gif")]
private var MyLogoClass: Class;
private var _logo : Bitmap;
private var _logoData : BitmapData;
private var isReady : Boolean = false;
public var progress : Number;
//~ Constructor -------------------------------------------------------
public function LoadScreen()
{
super();
this.progress = 0;
this._logo = new MyLogoClass as Bitmap;
}
//~ Methods -----------------------------------------------------------
public function refresh() : void
{
this._logoData = this.draw();
var encoder : PNGEncoder = new PNGEncoder();
var bytes : ByteArray = encoder.encode(this._logoData);
this.loadBytes(bytes);
}
override public function get width() : Number
{
return Math.max(_BarWidth, _LogoWidth) + _LeftMargin + _RightMargin;
}
override public function get height() : Number
{
return _LogoHeight + _BarHeight + _Padding + _TopMargin + _BottomMargin;
}
private function draw() : BitmapData
{
// create bitmap data to create the data
var data : BitmapData = new BitmapData(this.width, this.height, true, 0);
// draw the progress bar
var s : Sprite = new Sprite();
var g : Graphics = s.graphics;
// draw the bar background
g.beginFill(_BarBackground);
g.lineStyle(2, _BarOuterBorder, 1, true);
var px : int = (this.width - _BarWidth) / 2;
var py : int = _TopMargin + _LogoHeight + _Padding;
g.drawRoundRect(px, py, _BarWidth, _BarHeight, 2);
var containerWidth : Number = _BarWidth - 4;
var progWidth : Number = containerWidth * this.progress / 100;
g.beginFill(_BarColor);
g.lineStyle(1, _BarInnerColor, 1, true);
g.drawRect(px + 1, py + 1, progWidth, _BarHeight - 3);
data.draw(s);
// draw the logo
data.draw(this._logo.bitmapData, null, null, null, null, true);
return data;
}
public function set ready(value : Boolean) : void
{
this.isReady = value;
this.visible = !this.isReady;
}
public function get ready() : Boolean { return this.isReady; }
}
}
I feel dumb...I was referencing one of my main application classes from within the preloader, thus causing all of my classes to be compiled into the preloader, meaning it cannot display the preloader until everything is loaded.
For future reference: Double-check every reference in your preloader, make sure you use nothing more than what is absolutely necessary
There is a Flex 4 Custom Preloader code sample here http://www.leavethatthingalone.com/blog/index.cfm/2009/11/11/Flex4CustomPreloader

Resources