02-09-2010, 04:17 AM
|
#1
|
|
Senior Member
Join Date: Sep 2008
Posts: 147
|
Access method from an embedded SWF
Hi,
It is possible to access a method in an embedded SWF? For example, here's the SWF that I want to embed:
Code:
package
{
import flash.display.Sprite;
import flash.events.Event;
/**
* ...
* @author
*/
public class Main2 extends Sprite
{
public function Main2():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
}
public function load(str:String):void
{
trace(str);
}
}
}
And here's the parent SWF:
Code:
package
{
import flash.display.Sprite;
import flash.events.Event;
/**
* ...
* @author
*/
public class Main extends Sprite
{
[Embed(source="../../ChildSWF/bin/ChildSWF.swf")]
public var SWF:Class;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
var swf:Object = new SWF();
swf.load("hello");
}
}
}
When I run this, I get the following exception:
ReferenceError: Error #1069: Property load not found on Main_SWF and there is no default value.
Is what I'm trying to do possible?
|
|
|
02-09-2010, 05:20 AM
|
#2
|
|
Super Moderator
Join Date: Dec 2007
Location: Greenville, SC
Posts: 6,508
|
it's possible and there's basically a dirty way which most people use and a clean way which I use (I'm not the only one of course).
Dirty way: Cast to MovieClip and take advantage of the dynamic property of MovieClip by calling a non existing method:
ActionScript Code:
var swf:movieClip = new SWF() as MovieClip;
swf.load("hello");//compiler can't tell you wrong so you succeed
Clean way: Make your swf a datatype and make sure the loading swf knows the type:
ActionScript Code:
//theorical
var swf:Main2 = new SWF() as Main2;
swf.load("hello");//compiler knows what's a Main2 and the call succeed
But more to the point that's where Interface can get into play:
ActionScript Code:
//theorical
var swf:Iloaded = new SWF() as Iloaded;
swf.load("hello");//compiler knows what's a Iloaded and the call succeed
|
|
|
02-09-2010, 05:30 AM
|
#3
|
|
Senior Member
Join Date: Sep 2008
Posts: 147
|
Thanks, I'll try out the "clean way."
However, I don't understand the difference between your last two examples.
|
|
|
02-09-2010, 05:34 AM
|
#4
|
|
Super Moderator
Join Date: Dec 2007
Location: Greenville, SC
Posts: 6,508
|
Quote:
Originally Posted by web developer
I don't understand the difference between your last two examples.
|
An Interface is basically an empty class just enumerating the method signatures while a class like Main2 does enumerate the methods but provides also the implementation. So the difference between them is the file size that they generate. When you load an external swf you probably don't wnat to import in the loading swf the class that you already use in the loaded swf since that would mean having twice the same class and file size added. The Interface does not provide implementation and therefore is light weight.
|
|
|
02-09-2010, 05:43 AM
|
#5
|
|
Senior Member
Join Date: Sep 2008
Posts: 147
|
So have an interface that Main2 implements and cast to that instead of the Main2 class? This is a good idea but the interface class could become not generic if I want to have complex arguments passed to the method.
|
|
|
02-09-2010, 07:22 AM
|
#6
|
|
Senior Member
Join Date: Feb 2006
Posts: 682
|
The problem you're having is because when you embed a swf, it's not embedded as a MovieClip or Sprite, it's a MovieClipLoaderAsset. In your parent swf, change swf.load("hello") to swf.content.load("hello"). You may have to cast the content to an Object to access the load() method: Object(swf.content).load("hello");
|
|
|
02-09-2010, 09:19 AM
|
#7
|
|
Senior Member
Join Date: Mar 2009
Location: Sweden
Posts: 9,790
|
The Object class is already dynamic, the issue is not a compiler error. The error is due to the embed tag corrupting the embeded swf file by replacing the main timeline class. You can not use it like this. You need to embed it as a bytearray so that the compiler stops corrupting your data.
__________________
Signature: I wrote a pair of articles about the timeline.
|
|
|
02-09-2010, 05:19 PM
|
#8
|
|
Senior Member
Join Date: Feb 2006
Posts: 682
|
Quote:
Originally Posted by henke37
The Object class is already dynamic, the issue is not a compiler error. The error is due to the embed tag corrupting the embeded swf file by replacing the main timeline class. You can not use it like this. You need to embed it as a bytearray so that the compiler stops corrupting your data.
|
You do not need to embed it as a byte array. What I said above is true; when you embed a swf the way he did it is not corrupt, it is a MovieClipLoaderAsset, which is a Loader added to a MovieClip: http://livedocs.adobe.com/flex/3/lan...aderAsset.html The Loader contains your embedded swf.
I did make a mistake in my code though, the first child is the loader, so in the example above you would use Loader(swf.getChildAt(0)).content.load("hello"); Before you access the content you also need to have an event listener that either listens for the COMPLETE event, or use an ENTER_FRAME event to wait a couple frames. When you embed swf's this way I have found the ENTER_FRAME to be more reliable. There was a discussion about this a couple weeks ago, embedding as a byte array will always work correctly with a COMPLETE, but a MovieClipLoaderAsset doesn't, at least not in my experience...that's why I use ENTER_FRAME.
Here is a simple example of how to get at the content of your embedded swfs: http://www.bit-101.com/blog/?p=1435
Last edited by krayzeebean; 02-09-2010 at 08:39 PM.
Reason: clarification
|
|
|
02-10-2010, 03:41 AM
|
#9
|
|
Senior Member
Join Date: Sep 2008
Posts: 147
|
What ASWC suggested did not work for me.
I am also not able to get krayzeebean's suggestion to work:
ActionScript Code:
package
{
import adobe.utils.CustomActions;
import flash.display.Loader;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.SWFVersion;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import local.ChildSWF;
/**
* ...
* @author
*/
public class Main extends Sprite
{
[Embed(source="../../ChildSWF/bin/ChildSWF.swf")]
public var SWF:Class;
public static const NUM_FRAMES:int = 5;
public var m_numFrames:int;
public function Main():void
{
m_numFrames = 0;
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
addEventListener(Event.ENTER_FRAME, enterFrame);
}
public function enterFrame(e:Event):void
{
m_numFrames++;
if (m_numFrames == NUM_FRAMES)
{
removeEventListener(Event.ENTER_FRAME, enterFrame);
var swf:Sprite = new SWF();
//Object(swf.getChildAt(0)).print("hello");
//Loader(swf.getChildAt(0)).content.print("hello");
}
}
}
}
If I uncomment out Object(swf.getChildAt(0)).print("hello");, I get the following runtime error:
ReferenceError: Error #1069: Property print not found on flash.display.Loader and there is no default value.
If I uncomment out Loader(swf.getChildAt(0)).content.print("hello"); I get a compilation error saying that the "print" method is not defined.
|
|
|
02-10-2010, 05:50 AM
|
#10
|
|
Senior Member
Join Date: Feb 2006
Posts: 682
|
You need to cast the content as Object. It is a DisplayObject, which of course doesnt' have your print() function so Flash is giving you a compile error. You also need to instantiate the SWF class in your init function. The enter frame event is to give it enough time to initialize. Getting to your print() function can be done in fewer lines, but I've broken it up to (hopefully) make it a little clearer.
ActionScript Code:
package
{
import adobe.utils.CustomActions;
import flash.display.Loader;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.SWFVersion;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import local.ChildSWF;
/**
* ...
* @author
*/
public class Main extends Sprite
{
[Embed(source="../../ChildSWF/bin/ChildSWF.swf")]
public var SWF:Class;
public static const NUM_FRAMES:int = 5;
public var m_numFrames:int;
private var swf:Sprite;
private var embeddedContent:Sprite;
public function Main():void
{
m_numFrames = 0;
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
swf = new SWF();
addEventListener(Event.ENTER_FRAME, enterFrame);
}
public function enterFrame(e:Event):void
{
m_numFrames++;
if (m_numFrames == NUM_FRAMES)
{
removeEventListener(Event.ENTER_FRAME, enterFrame);
var loader:Loader = swf.getChildAt(0) as Loader;
embeddedContent = loader.content as Sprite;
addChild(embeddedContent);
Object(embeddedContent).print("hello");
}
}
}
}
|
|
|
| Thread Tools |
|
|
| Display Modes |
Rate This Thread |
Linear Mode
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT. The time now is 02:37 PM.
///
|
|