timmaktu
timmaktu

Reputation: 163

AS3 Event Architecture Issue

Before calling the function addNodeFilled() that uses an external bitmap file as a fill I must load the bitmap file in flash player using Loader class and wait for the loader to finish loading and fire Event.COMPLETE and execute the corresponding event handler onComplete(). To ensure this I have a while loop to wait for completion of loading in addNodeFilled(), but when running the program the program esp the loop goes on infinitely which means in flash the event handler is executed synchronously with the main sequence and can't execute until addNodeFilled() ends. Usually the code in addNodeFilled() is placed inside onComplete event handler but I am unable to do that and need to call addNodeFilled() whenever I wish but check for load completion, how can I do that?

var stitch:BitmapData = new BitmapData(16, 16);
var loaderStatus:String = "busy";           

var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest("file:///E:/Projects/FlashDevelop/Terracotta/assets/Stripe.jpg"));

addNodeFilled(100, 100);



//function definitions===============================================


function onComplete(event:Event):void
{
  stitch = event.target.content.bitmapData;
  loaderStatus = "loaded";

} //onComplete

function addNodeFilled(posx:Number, posy:Number):void
{
  while(loaderStatus != "loaded")
  {
     trace("waiting for loader");
  }         

  var grid:Rectangle = new Rectangle(5, 5, 5, 5);
  var nodeDecal:Sprite = new Sprite();
  nodeDecal.graphics.beginBitmapFill(stitch, null, true, true);
  nodeDecal.graphics.drawRoundRectComplex(posx, posy, 80, 16, 0, 0, 4, 4);
  nodeDecal.scale9Grid = grid;
  addChild(nodeDecal);

} //addNodeFilled

Upvotes: 1

Views: 89

Answers (1)

Pranav Negandhi
Pranav Negandhi

Reputation: 1624

AS3 executes on a single thread. You'll never receive any event notifications with that loop. I've mocked up a better pattern with the code below. You'll have to adapt it a bit to your needs. Notably, you'll have to move the drawing code out from addNodeFilled() and into its own method, that can be called from addNodeFilled() or from onComplete(), as necessary.

If there are multiple draw operations, you'll have to replace the drawPending variable with a queue, that gets executed after the asset is loaded. I've not mocked it here because it can increase the code complexity significantly.

var loader:Loader;
var loadPending:Boolean = false;
var isReady:Boolean = false;
var drawPending:Boolean = false;

function onComplete(event:Event):void
{
    if (drawPending)
    {
        // Perform drawing operating
    }
}

function triggerLoad():void
{
    loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
    loader.load("http://example.com");

    loadPending = true;
}

function addNodeFilled(x:Number, y:Number):void
{
    if (!isReady)
    {
        triggerLoad();
        drawPending = true;

        return;
    }

    if (loadPending)
    {
        drawPending = true;

        return;
    }

    // Use asset as needed
}

Upvotes: 1

Related Questions