I'm programming an AS3 application which loads an external SWF file to a movie clip in my stage. I need to read a variable inside the embedded SWF. I think I can, probably, do this through the bgURL, but I can't figure out how.
How can I read a variable inside the embedded SWF?
var bgLoader:Loader = new Loader();
var bgURL:URLRequest = new URLRequest("file.swf");
bgLoader.load(bgURL);
addChild(bgLoader);
That would be something like trace(MovieClip(bgLoader.content).Player.played);, but make sure you access the content in the Event.COMPLETE handler:
bgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,bgLoaded);
function bgLoaded(event:Event):void{ trace(MovieClip(bgLoader.content).Player.played) }
bgLoader.content returns a DisplayObject, but you need to access you content as a MovieClip. To do so you use casting.
This is presuming your external swf is also AS3 (good point Teo.sk !)
This bit: _root.Player.played looks like AS2. Unfortunately you can't access
variables form a loaded AS2 movie directly.
Still, you can use Local Connection class to send variables back and forth betwen
AS2 and AS3. Luckily Grant Skinner wrote a nice little utility called SWFBridge
to make this easier
Related
I'm learning Flash Builder so I can add some extra functionality to my Flash Pro project.
Let's say I create a new Flash Pro file called foo.fla. I can then open Flash Builder and create a new project (and in the setup wizard I specify my foo.fla file as the target of the project). The wizard then creates a new project containing one file called foo.as which extends Sprite.
Now I would expect this initial file to be a root of some kind, and a great central place where I could create variables that all my MovieClips need to share. However, I can't figure out what exactly this file is being used for when my project is run. It doesn't seem to correspond to the stage or to the parent of any of my movie clips. It's constructor doesn't even seem to be called. What is this file used for? Is there a way I can use it to store 'global' stuff?
In order to "link" it to your FLA, you'll want to set it as the document class:
Once you do that, the constructor should be called at startup.
This class is exactly what you think it is: root*.
The class that you provide is the class that is associated with your .fla file.
It is called the document class or main class.
You are probably familiar with the concept of associating a library symbol with a class.
Say you create a MovieClip, add it to your library and define a class for it.
This is pretty much the same thing now, except you add the class to the document.
When the flash player executes your .swf file, it will instantiate your class and add it to the display list. This has a couple of implications:
The class must be some DisplayObject, because it is added to a DisplayObjectContainer.
This is why you it extends Sprite. (Sprite is a lightweight class that you should prefer over MovieClip if you do not need a timeline)
This is the strange part, remember * up there?
Yes, as your swf is created, the document class is instantiated and the resulting object is added to the display list, this means that root isn't actually the root of the display hierarchy. There's a parent container and that is stage.
Think of root as the root of your application, not necessarily the top most root of all roots.
And here's the (imo) strangest thing:
You can access the stage property within the constructor of the document class.
This is not true for any other class that extends DisplayObject (unless you force it by passing stage as a parameter to the constructor, which you shouldn't be doing)) and who's objects will end up on the display list, because you have to addChild them after they are created.
You might be tempted to use the stage property in such a constructor that is a constructor of a document class (because you can), but this leads to problems, because you can never tell if your document class is actually used as a document class.
If you want to instantiate your current document class in some other project, it will not have the special status of being the document class. It will be some regular class as all the others of that project.
In this case, stage will be null in the constructor. So don't access stage in the constructor, even if you can.
If you need stage, wait for it to be available. That is when the ADDED_TO_STAGE Event fires.
I know this is kind of a strange thing to I want to find, but here is a little backstory as to why I'm trying to do this:
I am making an online multiplayer flash game. I am using flash builder and flash professional for writing as3 and working with graphics. I am also running a development server (by playerio in visual studio ultimate). The way I am testing this online multiplayer game is by running the swf once from flash professional and once from flash builder. They are both connected to the exact same action script 3 code and flash movie clips (via a swc file). I like this setup a lot because flash pro and flash builder each have their own little output area, and I can see the debugging output for each user separately.
The Problem
Although the two swf's are running the exact same code, I want them to behave differently. For example, the flash pro version gets a reference to the image from:
_gameOverPopup = this["gameOverPopup"];
and the flash builder user gets it like this:
_gameOverPopup = new GameOverPopup;
There are many other differences as well. For example, I am automatically authenticating and logging in with a different user in each case by just hardcoding username and password in. So now my code looks something like this:
if (inFlashBuilder) {
// this only happens when debugging in Flash Builder
authenticateWith("billyboy", "Secret123");
}
else {
// this only happens when debugging in Flash Professional
authenticateWith("joeshmoe", "password1");
}
This works great, but I am manually changing the inFlashBuilder variable in my code. I basically just have it at the top of the class:
private var inFlashBuilder:Boolean = true;
and I have to manually changing it from true to false each time before I compile. Oh man, I wish there were a method in System or something like that which I could use control this flag variable. If only...
You'll want to use compiler constants. FlashPro actually already sets one in regards to the IDE. You can access it as follows in AS3 (it will produce true or false):
CONFIG::FLASH_AUTHORING
So, you would want to do this:
if (CONFIG::FLASH_AUTHORING) {
// this only happens when debugging in Flash Professional
authenticateWith("joeshmoe", "password1");
}
else {
// this only happens when debugging in Flash Builder
authenticateWith("billyboy", "Secret123");
}
You'll want to set up the same constant in Flash builder but set the value to false.
In the flex-config.xml, add this:
<compiler>
<define append="true">
<name>CONFIG::FLASH_AUTHORING</name>
<value>false</value>
</define>
</compiler>
See this link to find out more about how to do this in flash builder:
http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7abd.html
If you don't want to build it twice, you can also have a post-build hook that copies the swf under a different name. Then, in your code, you can check this.loaderInfo.loaderURL and differentiate your logic that way.
if( this.loaderInfo.loaderURL.indexOf( "second.swf" ) )
// do alt logic
I have tried few things but no success.
I want to prompt user on button click event to save PDF file in local computer generated from object array which were created by user at runtime.
Any sort of help is greatly appreciated
Thanks
I have revised target flash player 10.0 in the html and somehow found out that the save event call has to be on button click event and I already have that. but still it gives me error and does not even generate swf file.
Here is the code and error.
1061: Call to a possibly undefined method save through a reference with static type flash.net:FileReference. It gives me this error.
var cFile:FileReference = new FileReference();
var gBytes:ByteArray = this._myPDF.save(Method.LOCAL);
cFile.save(gBytes,"test.pdf");
You can try the following, if you want to make download by using specific URL(where file is stored).
var urlRequest:URLRequest = new URLRequest("your_pdf_url");
fileRef = new FileReference();
fileRef.download(urlRequest, "your_file_name.pdf");
If you just want to prompt user to save the file in local system, you can try FileReference for that.
like :
file = new FileReference();
file.addEventListener(Event.COMPLETE, completeHandler);
file.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
file.save(mc, "myMovieClip");
here mc is any type of data you can provide, in your case you can provide your dynamically generated PDF file, and "myMovieClip" is name which you wan to give that file.
try this, might be useful for you.
I was using CS3 and changing the target player to 10 in HTML but found out that can not be simple. The compiler should have 10.0 as an option so I had to jump to CS6 and it worked as Vipul suggested. target player I had to keep 10.3. I had to change one more thing which is not related to this PDF saving. And that is VideoEvent to Event. I am wondering why adobe had to change that for FP 10 and above. Good to know if anybody want to use. Event.COMPLETE not VideoEvent.COMPLETE once again thanks a lot Vipul I will check the second import statement flash.utils.ByteArray. I must have because I did not get any error
I have this flash game that I've been working on that works out of the browser, and I'm looking to get it to save it's progress.
I've seen multiple flash games that have accomplished this, and It appears as though they've done this client-side, and I'd like to do the same.
My game consists of 1 mxml file and a number of .as files and I compile it from the command line using flex sdk.
What do I have to do to be able to save save my game's data?
As others have mentioned, SharedObject is the tool you'll use for this.
The basics of this are to initialize a reference to a SharedObject using its static method .getLocal() first:
var mySaveData:SharedObject = SharedObject.getLocal("SomeSaveName");
The String given to this method should not contain spaces.
Once you've done this, you'll be able to use mySaveData.data, which is basically a simple object that you can attach properties to on the fly (it's dynamic):
mySaveData.data.levelsComplete = 2;
Once you've done this, you'll be able to reference that value later on using the same process:
trace( mySaveData.data.levelsComplete );
For simple stuff you can use SharedObject
One way is to use flash's SharedObject to save values in to a 'flash cookie' on the client. Example can be found here: Actionscript 3 saving currentframe location to local hard drive?
I need some clarification on this subject as I just ran into an issue with loading swfs into a reused loader object.
So lets say I have 3 SWFs.
Main.swf
childA.swf
childB.swf
Main.swf has a loader object in it that gets reused (myloader.load("childA.swf")) and childA or childB swf will be loaded via user interaction.
Both child swfs have a com package with a class in that package called config.
The config files are different files for both classes just named the same.
both child swf also dispatch an event that the Main listens for
Now the problem I had was if childA was loaded first then after childB was loaded it would still show as childA. Basically, whichever one got loaded into that loader first would be the winner.
This drove me nuts as nothing I did would cause the swf to unload. Not until I found the following code.
var appDomain:ApplicationDomain = new ApplicationDomain();
var context:LoaderContext = new LoaderContext(false, appDomain);
_contentPanel.load(new URLRequest(str), context);
I stumbled over this code on a post somewhere talking about how to truly unload a swf. Apparently, This also applies to how to truly load a swf.
As you can see a new appDomain is created and assigned to the context when loaded.
This works like a dream I can now load and unload all day long.
My confusion is the event that the child dispatches still works, when I don't think the Main swf should pick it up due to it not being in the same appDomain.
I mean shouldn't the event be blocked?
Unloading a SWF
The Loader class provides Loader.unload() (or after Flash Player vers. 10 - Loader.unloadAndStop())
Problem with the second loaded SWF being overridden by the first
Objects that are stored in ApplicationDomains are stored by their class-name and I wonder whether the class names of the loaded SWFs (or their children) are overriding. Even if that isn't the case; why not use a new instance of the Loader for each object being loaded?
How the Main SWF can pick up both children from another application domain
The Main SWF will be able to work with the new (loaded) application domains because they are child-domains of the Main SWF's (See ApplicationDomain.parentDomain). The Main SWF's domain will be the 'system domain' and the new instances will be loaded below it.
Splitting the loaded SWFs from the Loader
Ideally you want to have access to the SWF data irrelevant of the state of the Loader. You can do this by accessing the root movieClip of the SWF once loaded and create a new instance with
var rootClipClass:Class = ApplicationDomain.getDefinition("[InsertYourRootClipName]") as Class;
var rootClip:MovieClip = new rootClipClass();
At that point you can unload the loader and work with your fresh instance cleanly.
Further reading
Difference between Loader.unload() and Loader.unloadAndStop()
Working with Application Domains - Adobe Docs
Loader class reference
ApplicationDomain class reference