2
votes

I have a full browser window AS3 Flash CS4 parent swf which loads a third-party child swf, smaller in height/width and positioned appropriately (i.e. centered). No matter what loading technique I try to use, I'm running into placement and orientation problems in the child swf which break the child.

In one example case, the child will load a secondary displayobject (presumably a movieclip), but attempts to attach it to the stage. If I allow it access to the stage via the SecurityDomain during loading, it orients it at 0,0 of the parent swf instead of 0,0 of the child swf (which is already position/centered appropriately).

In another, the child positioning during load is appropriate, but placement inside the child which seem to reference the stage for their X,Y positions is offset by the amount the child swf has been centered (i.e. if the loader of the child swf is centered such that it's X is at 200, and an object inside the child swf is supposed to be at 100,50, it is actually at 300,50).

The common thread seems to be that the child swfs, whether or not allowed to access the stage, are using stage or player properties of the parent instead of those of their own within the loader.

How can I isolate the child swf such that it only uses it's own sub-environment for positioning and orientation and not the parent's?

I have tried the built-in Loader and UILoader, Greensock's SWFLoader, Flex's SWFLoader and even loading it via text in a TextField.

It seems like AIR's HTMLLoader would work (since SWF objects inside the HTMLLoader apparently use their own stage object), but this app has be available in the browser.

Ideally, I'd still like to be able to communicate with the child, but at this point ensuring the child runs successfully is more important.

This seems like a common approach, yet running into blocking issues left and right make me think I'm approaching this in the wrong way.

My last resort is to replace the parent swf with a JS framework, but only if absolutely essential.

Suggestions for solutions at any part of this process would be appreciated.

2
This is my first question on SE, so please forgive any failure to follow SE protocols. - kfblake
have you tried lockroot? - The_asMan
@The_asMan, lockroot isn't available in AS3. But thanks for the thought. - kfblake
yeah my bad. You need to redevelop the child swf(s) to not target stage. Anytime you target stage you are losing the ability to port the swf or as you have found out a plethora or scoping will pop up on you. Instead of stage I would add a container in the child swf that will hold everything for you. If you need the child to access something in the parent or loading swf then you can just track back with parent.parent method. - The_asMan
Also have a look at root. As it seems "root" in a loaded swf will refer to the root of that swf. help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/… - The_asMan

2 Answers

2
votes

Hope there's not an SO "rule" against answering my own question...

As weltraumpirat mentioned in comments, there appears to be no way to restricted a loaded swf from accessing stage variables such as positioning/orientation (mouseX & mouseY). The best solution is to restrict access to the stage so that loaded swfs can not add to it. This is done by including a LoaderContext object with the Loader.load call which defines a separate ApplicationDomain.

var url:URLRequest = new URLRequest(/*...SWF URL...*/); 
var context:LoaderContext = new LoaderContext(false,new ApplicationDomain());
var ldr:Loader = new Loader();
ldr.load(url,context);

This will maintain a separate root in the loaded swf.

In cases where the Loader object has been positioned away from (0,0) in the parent/main swf, You may then need to coordinate with the loaded swf authors to wrap stage.mouseX & stage.mouseY with DisplayObject.globalToLocal to reflect the unknown offset (from within the loaded swf).

var localMousePt:Point = this.globalToLocal(new Point(stage.mouseX,stage.mouseY));

It sucks, but it makes sense from a security perspective. I've found that it's just common practice for a Flash developer to not think of the context in which their SWF might be loaded and therefore think nothing wrong with using the stage (instead of the root). Best practice should be to always use the root for adding and position objects because you never know where that root might be placed in the display list and how many parents their might be between it and the stage.

0
votes

This is an ugly hack, but you could always add a listener for Event.ADDED to the stage, check for the display objects that need to be adjusted (this works best if they're named, of course, but there may be other criteria you can use), and then change their coordinates manually.

private function onAdded( ev:Event ) : void {
     if ( ev.target.name == "whatever") 
         modifyCoordinates( ev.target as DisplayObject );
}

private function modifyCoordinates( target:DisplayObject ) : void {
    // displace to match parent clip
}

//...

stage.addEventListener( Event.ADDED, onAdded );

If there's no way to distinguish the display objects spawned by the loaded clip, you can instead filter out the ones you're adding to the stage yourself: If only the root MovieClip of your application is on the stage, and then everything is added as children to that, it should not be a problem at all.

I would also try to contact the author, or decompile the third-party files - if any of that works, you may at least learn about how things are done, so you won't have to guess where to apply your changes. Or perhaps you may even modify and recompile them.