Loading multiple external swf's

Posted by BruceND75 
Loading multiple external swf's
August 06, 2009 05:58AM
I am designing an application where, in order to keep load times down while maintaining flexibility, and to avoid the problems with FlashEff and multiple scenes, the application loads a number of external SWF's, and then plays each SWF sequentially. Each external SWF is equivalent to a 'scene.'

I noticed that Papillion points out the need to use UILoader instead of Loader so that the FLashEff components in each can play without having to import the external SWF's components into the master application SWF.

I noticed also that -- when testing the app -- I get none of the text effects . . . and that demiurgu pointed out that each external SWF needs to be in it's own application domain.

Since the concept of context and application domains is totally new to me, I could use a bit of help figuring out how to construct.

Here is the pertinent code before context:

var thisUILoader:UILoader = new UILoader();
thisUILoader.addEventListener(Event.INIT, doneLoading);

thisUILoader.load( new URLRequest(clips[index]) ); // where clips is an array which gets cycled through

////////

This is the code suggested by demiurgu:


var swfRequest:URLRequest = new URLRequest("loaded.swf");
separateDefinitions:LoaderContext = new LoaderContext();
separateDefinitions.applicationDomain = new ApplicationDomain();
var swfLoader = new Loader();
swfLoader.load(swfRequest,separateDefinitions);

///////

What would be the correct construction to allow separate application domains for each external SWF?
Re: Loading multiple external swf's
August 10, 2009 07:15AM
After a long weekend, I came up with a workable, baseline design. While I plan on developing this further, I thought you all might be interested in how to put this together, so here is the code.

Assumption: Each external clip ends with a "stop();" on the final frame.

// with credit to the script provided at [www.flashandmath.com]

import fl.containers.UILoader;

// Array of external clips to use. Variable index refers to next clip to be displayed.

var clips:Array = ["Clip1.swf", "Clip2.swf", "Clip3.swf"];
var index:int = 0;

// Stuff for loading files

var thisUILoader:UILoader = new UILoader();
thisUILoader.addEventListener(Event.INIT, doneLoading);

var theLoaderContext:LoaderContext;

var thisMC:MovieClip = new MovieClip();

stage.addChild(thisMC); // Add empty MC initially so the nextClip function works even on first call

// Gets the next MC, waiting for INITialization before adding it to the stage

function nextClip():void {
	
	theLoaderContext = new LoaderContext();
	theLoaderContext.applicationDomain = new ApplicationDomain();
	thisUILoader.load( new URLRequest(clips[index]),theLoaderContext);

}

function doneLoading(e:Event):void {

	stage.removeChild(thisMC);	
	thisMC = MovieClip(thisUILoader.content);
	thisUILoader.unload();	
	thisMC.addEventListener(Event.ENTER_FRAME, runOnce);	
	stage.addChild(thisMC);	
	thisMC.gotoAndPlay(1);

}

// When thisMC has finished, play the next clip.

function runOnce(e:Event):void {
	
	if (thisMC.currentFrame == (thisMC.totalFrames-1)) {
		
		thisMC.removeEventListener(Event.ENTER_FRAME, runOnce);
		index = (index + 1)%(clips.length);
		nextClip();
	
	}
}

// Call the nextClip function initially to get the ball rolling

nextClip();

Re: Loading multiple external swf's
August 10, 2009 12:53PM
This is great, thank you. I will personally make sure you get a discount for posting this.
I hope you will keep posting stuff like this, it really helps the users alot.
Re: Loading multiple external swf's
August 11, 2009 09:45AM
Thanks for the kind words, Ionut. In case you and/or others are interested in watching this evolve, I'm posting my next "version" of my app. Some might pick up some things by seeing the steps. In the meantime, anyone can take the code, paste it into a Flash or Flex app, and play a string of FlashEff'd SWF's.

My main goal the first try was just to get the elements (UILoader, LoaderContext, and a Slideshow app) working together.

My main goal on this second go round is to separate the loading and playing functions. My first slide/scene/swf is very small, but the second is very large. I'd like to load the first, let the user start reading while loading the second, so it is ready when the user moves on (or the slideshow plays on). The yesterday's version didn't start loading until the next slide is called up -- making the user do the waiting I was specifically trying to avoid.

If you look below, you'll see that the loader kicks in and goes about it's loading until it's done. It "unloads," if you will, into a multi-dimensional array where I store the external swf (in it's own applicationDomain) and a boolean value to track whether the swf has been loaded.

The other half of the app -- the 'slideshow' player -- kicks in when the first external swf signals it is loaded. From there, the player (now) just plays on through. Later, will give scene next/previous controls to step through slides/scenes/swfs.

Here is tonight's code, then:

// with credit, again, to the script provided at [www.flashandmath.com]

import fl.containers.UILoader;

// Array of external clips to use. Will use XML file later

var clips:Array = ["ClipOne.swf", "ClipTwo.swf", "ClipThree.swf"];

// Variables for looping through clips to load them and, later, play them

var index:int = 0;
var clipNumber:int = 0;
var clipsLength:int = clips.length;

// Stuff for loading files

var thisUILoader:UILoader = new UILoader();
thisUILoader.addEventListener(Event.INIT, doneLoading);

// This creates a LoaderContext variable so that, later, each SWF will have it's own applicationDomain
var theLoaderContext:LoaderContext;

// First step in creating a multidimensional array that will contain each clip and a boolean value for "loaded"
var theMCs:Array = new Array(clipsLength);

// This creates a blank MovieClip that will first be placed in a couple of places
var thisMC:MovieClip = new MovieClip();

// Load the theMCs array with the blank MovieClip and "false" for "loaded"
var i:int;
for(i=0; i<clipsLength; i++) {

	theMCs[i] = new Array(2);

	theMCs[i][0] = thisMC;
	theMCs[i][1] = false;

}
stage.addChild(thisMC); // Add empty MC initially so the playMC function works even on first call

// Gets the next MC, waiting for INITialization before adding it to the theMCs array

function loadNextClip():void {
	
	theLoaderContext = new LoaderContext();
	theLoaderContext.applicationDomain = new ApplicationDomain();
	thisUILoader.load( new URLRequest(clips[index]),theLoaderContext);

}

// After each clip is done loading, it is placed in the theMCs array, with "true" for "loaded"
function doneLoading(e:Event):void {

	theMCs[index][0] = MovieClip(thisUILoader.content);
	theMCs[index][1] = true;

	// Clear the UILoader
	thisUILoader.unload();
	
	switch(index) {
	
		// If this is the first clip, the player can now be started
		case 0:
			playMC(); //start player
			
			// Load the next clip
			index = index+1;
			loadNextClip();
			break;
			
		// If this is the last clip, stop loading
		case clipsLength-1:
			//stop loading
			break;
			
		// Otherwise, just load next clip
		default:
			index = index+1;
			loadNextClip();
			break;	
	}
}

// This is initiated for the first time after the first clip is loaded, then each time a new clip is set to play
function playMC():void {

	stage.removeChild(thisMC);
	
	thisMC = theMCs[clipNumber][0];
	
	// This is a do-while loop that is invoked if the clip called is not loaded yet
	do
	{
		clipNumber = clipNumber; // This is just for waiting; not sure if it can be blank/empty, so . . .
		
	// Marches in place while the clip is still not loaded
	} while (theMCs[clipNumber][1] === false);
	
	// Duplicates the assignment above, in case the clip was not ready when first called & the clip is now ready
	thisMC = theMCs[clipNumber][0];	
	
	thisMC.addEventListener(Event.ENTER_FRAME, runOnce);	
	
	stage.addChild(thisMC);
		
	thisMC.gotoAndPlay(1);
}

// When thisMC has finished, play the next clip.

function runOnce(e:Event):void {
	
	if (thisMC.currentFrame == (thisMC.totalFrames-1)) {
		
		thisMC.removeEventListener(Event.ENTER_FRAME, runOnce);
		if (clipNumber<(clipsLength-1)) {
			clipNumber = clipNumber+1;
			playMC();
		}
	}
}

// Call the loadNextClip function initially to get the ball rolling

loadNextClip();

Hope some find this useful.
Re: Loading multiple external swf's
August 19, 2009 01:34AM
I want to provide an update to correct two things in my previous post. I've been busy with the project, porting it to Flex, and discovered two things.

First, while you can pop the above script into a Flash file and run it, the Flex is a bit more of a challenge. Fair warning.

Second, and most importantly, I discovered that the event listener for the UILoader needs to be changed.

Change the following code:
thisUILoader.addEventListener(Event.INIT, doneLoading);

to this:
thisUILoader.addEventListener(Event.COMPLETE, doneLoading);

The INIT event fires when the external SWF's methods are available. Turns out that I was unloading the UILoader before it had -- well, completely COMPLETE'd loading.

There. My conscience is clear now. : )
Re: Loading multiple external swf's
August 24, 2009 07:29PM
This is really helpful - any chance you know how to make it loop back to the first clip and start playing again?

Thanks
Re: Loading multiple external swf's
August 25, 2009 03:33AM
robcarey,

Thanks for the thanks!

That is a simple adjustment. The trick is to change the code above where it reads:

if (clipNumber<(clipsLength-1)) {
	clipNumber = clipNumber+1;
	playMC();
}


To the following:

if (clipNumber<(clipsLength-1)) {
	clipNumber = clipNumber+1;
} else {
	clipNumber = 0;
}
playMC();

The runOnce function is designed to determine when the playing clip has reached it's end. Then, in my version, I increment the clipNumber --- as long as the playing clip is not the last (i.e. clipNumber < clipsLength -1). In my version, if the playing clip IS the last one, I tell the app to stop playing at the end of the last clip (i.e. I don't invoke the playMC).

For your version, everything will be the same, except that when the app determines that it IS the last clip, then clipNumber is reset to 0 (i.e. the first clip's clipNumber) and the app then calls the playMC function with the new clipNumber.

That should take care of you. Let me know if I can help further.

Bruce
Re: Loading multiple external swf's
September 25, 2009 06:31PM
Hi BruceND75 - I think your solution is exactly what I'm looking for... I have a somewhat complex presentation that I want to deliver using FlashEff effects...

However, I'm also a little new to Flash -

Do you have a primer or some basic step-by-step on how to set this all up? I created a new SWF using the same dimensions as two child swfs that I want to load into the parent. On the parent SWF - I placed your script into the first frame... is that correct? The parent and children are published to the same folder...

Thanks for any ideas and assistance!
Re: Loading multiple external swf's
January 26, 2010 04:04PM
Hey BruceND75, did you ever get around to making this script utilize xml for specifying the clips rather than hardcoding the array? That would be very nice.
Re: Loading multiple external swf's
January 27, 2010 06:01AM
jasonjulien Wrote:
-------------------------------------------------------
> Hey BruceND75, did you ever get around to making
> this script utilize xml for specifying the clips
> rather than hardcoding the array? That would be
> very nice.

jasonjulien,

It is still on my todo list. May be getting to it soon.

If you want to give it a try, feel free. I can give you a hand if you need it. Otherwise, will raise the priority on it and get back soon.
Re: Loading multiple external swf's
July 03, 2010 03:43AM
I know this is a topic that is over a year old but I need something like this and can't get this to work.
I am loading an array of URLs using URLLoader and then trying to process them using this code.
I need to know when to swap out the movies to the next one in the array.
Re: Loading multiple external swf's
July 06, 2010 07:19PM
Jasonjulien, i was working on a similar project and got the XML loader to work good. It actually pulls its data from a Drupal CMS. The problem is, when the external SWFs are loaded into the first, they lose their FlashEff2 animations and the execution just stops. I have debug code in it that shows that the frames just stop running when it hits the FlashEff2. It seems like a similar problem to others. But you can take the XML loader. That part works great. its about 98% to completion...

-Tim
Re: Loading multiple external swf's
September 17, 2010 11:24AM
Hi

The second code works fine until I test it through, simulate download with T1 speed.

The error is
"A script has executed for longer than the default timeout period of 15 seconds.
at Flasheff_multi2_fla::MainTimeline/playMC()
at Flasheff_multi2_fla::MainTimeline/runOnce()"

The three swf files I am playing are 2.5 MB, 21MB and 6MB respectively.

Please let me know how to make it function.

Thanks

Solly
Re: Loading multiple external swf's
January 30, 2016 06:34AM
Perhaps the best investment, though, is a social media manager. Rather than focusing on numbers, a manager can help you develop a complete social media marketing strategy that will help you turn those numbers into investors for your startup. <a href="[imgfave.com] page with most likes</a>
Sorry, you do not have permission to post/reply in this forum.