LoadVariables doesn't work as it is on Adobe website - actionscript-3

I am trying to learn and get used to ActionScript. I have a simple task: to use the loadVariables(); function. I tried to use the Adobe's official reference, but as usual, the references code doesn't work as it is there. Here is my code:
import flash.events.MouseEvent;
function buttonClicked( evt:MouseEvent ) {
this.createEmptyMovieClip( "variables_mc", this.getNextHighestDepth() );
loadVariables("info.txt", variables_mc);
trace( variables_mc.username );
}
this.myButton.addEventListener( MouseEvent.CLICK, buttonClicked );
I get three errors from the debugger:
#1 1180: Call to a possibly undefined method loadVariables.
#2 1120: Access of undefined property variables_mc.
#3 1120: Access of undefined property variables_mc.
Here is the page where I have taken the code from: http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00000575.html
Can anyone help me?
Thank you, and a Happy New Year!

So as stated in the comments AS2.0 holds the methods createEmptyMovieClip() and loadVariables(), since AS3.0 does not contain these global functions you'll need to use the URL libraries instead.
For example:
//declare target movieclip
var variables_mc:MovieClip;
function buttonClicked( evt:MouseEvent ) {
variables_mc = new MovieClip();
getVariables();
}
function getVariables():void {
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener( Event.COMPLETE, setVariables );
urlLoader.load( new URLRequest( "info.txt" ) );
}
function setVariables( e:Event ):void {
//then let's say you have userName=testUser in your info.txt
var urlVars:URLVariables = new URLVariables( e.target.data );
variables_mc.name = urlVars.userName;
}
Edit: I should explain what is happening here a little, URLLoader is the actionscript class used for loading files see: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLLoader.html
Once the file has been loaded setVariables() is called and URLVariables acts as a dynamic class which sets properties to the files variables. So in this case our text file contains the userName=testUser. URLVariables runs a method called decode() from the constructor with the parameter e.target.data and creates all the necessary fields. Lastly you can access them, in our case urlVariables.userName.
Anyway I hope this helps, I've only used this a couple of times as it is usually best to create a class that handles all this for you.

Related

ActionScript code problems

I have only recently started to learn ActionScript 3.0 I was practising in Flash and i ran into this problem:
Scene 1, Layer 'Layer 1', Frame 1, Line13 1119: Access of possibly undefined property dosomething through a reference with static type flash.net:SharedObject.
What i am tring to do is use the SharedObject.send method to send a message obviously. I have edited some server side code in my main.asc file. And i am trying to pass in the doSomething function but i get that compile error.
Any advice would be appreciated for a novice like myself.
The code is below:
import flash.net.NetConnection;
import flash.net.SharedObject;
var nc:NetConnection = new NetConnection();
nc.connect("rtmp:/exampletest/");
var so:SharedObject = SharedObject.getRemote("foo", nc.uri, true);
so.connect(nc);
so.dosomething = new function(str) {
If you want to pass a function between SWFs, attach the function to the .data member of the SharedObject returned by SharedObject.getLocal/Remote, not the SharedObject itself.
So:
so.data.doSomething = yourFunction
...should work. I'm not exactly sure what you're trying to achieve, does this sound like a solution?

Action Script 3 new loader

I was revisiting some code for a simple picture viewer that I created in Action Script 2.0 now taking on the same task in AS3. At present i'm well aware that the command .loadMovie is no longer used. After numerous attempts to find a solution I have come up dry.
At the moment I have a movie clip symbol(target_mc) on the stage that I want to load jpegs from a external file when I mouseOver a button. Can any one give a example of how this should be approached using the "new load" variable.In the AS2 version i also used (on release) in the button code.
training_btn is the button instance.
Please see an example of my code below:
training_btn.addEventListener(MouseEvent.CLICK, imageOver);
function imageOver(evt:MouseEvent) {
this.target_mc.loadMovie("galleryimage/p_traininglink.jpg")
}
Any ideas would be very helpful.
Wayne
Here at the Republic of Code is an excellent step-by-step tutorial on how to work with the loader class in as3
Yeap
training_btn.addEventListener (MouseEvent.MOUSE_UP, onMouseUp);
function onMouseUp (evt:MouseEvent):void {
var my_loader:Loader = new Loader();
my_loader.load(new URLRequest("myPhoto.jpg"));
target_mc.addChild(my_loader);
}
So, basically the whole structure of the laoder has change between AS 2 and 3.
Now you need to create a different object that loads the content.
var loader:Loader = new Loader();
Than you can do two things:
Add event listener and than trigger the load
Trigger the load and add the loader to the stage
The difference between these two style is big, the first one will add a listener and wait for the load to complete and after that it will call a method you define in the listener to do any further instuctions.
The second one starts loading the content and adds the loader to the display list so that when the content is loaded it automatically displays.
1.
// add the listener
laoder.contentLoaderInfo.addEventListener( Event.Complete, onLoadComplete );
// trigger the load (remember: the url is alwais a URLRequest object)
loader.load( new URLRequest("path_to_file") );
// additional var for storing the content (only the content, without the loader)
var content:Bitmap;
function onLoadComplete( e:Event ):void{
content = e.target.content as Bitmap;
// you could use also:
// content = loader.content as Bitmap;
// you can do some modifications before displaying the content
// and finally add it to the display list
this.target_mc.addChild( content );
}
2)
// trigger the load (remember: the url is alwais a URLRequest object)
loader.load( new URLRequest("path_to_file") );
this.target_mc.addChild( loader );
The two ways are correct but I prefer using the first one cause it gives you more controll. You can also check out the progress of loading by listening to the ProgressEvent.PROGRESS.
link: Loader Documentation
link: URLRequest Documentation
Hope it helps. Search in google for more info about loading external data, there's a lot of resource about that.
It would probably best to create a Class that would handle all of this, but to answer your question, your code would look something like:
var outLoader:Loader = new Loader();
outLoader.load(new URLRequest("outImage.jpg"));
var overLoader:Loader = new Loader();
overLoader.load(new URLRequest("overImage.jpg"));
overLoader.visible = false;
var training_btn:Sprite = new Sprite();
training_btn.addChild(outLoader);
training_btn.addChild(overLoader);
training_btn.buttonMode = true;
training_btn.mouseChildren = false;
training_btn.addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
training_btn.addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
addChild(training_btn);
function rollOverHandler(e:MouseEvent):void {
overLoader.visible = true;
}
function rollOutHandler(e:MouseEvent):void {
overLoader.visible = false;
}

How to get all definitions in an ApplicationDomain of a loaded SWF?

When you load a SWF into another, the loader SWF can get specific definitions from the loaded SWF using ApplicationDomain.getDefinition(name:String). For example:
package
{
// ... imports
public class SWFLoader extends Sprite
{
private var loadedAppDomain:ApplicationDomain;
public function SWFLoader()
{
var request:URLRequest = new URLRequest("test.swf");
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTestLoadComplete);
loader.load(request);
}
private function onTestLoadComplete(event:Event):void
{
var loaderInfo:LoaderInfo = LoaderInfo(event.target);
loadedAppDomain = loaderInfo.applicationDomain;
// Here we can get ANY defined symbol (class, namespace or function according to Adobe Flash help)
var someSymbolClass:Class = Class(loadedAppDomain.getDefinition("SomeSymbol"));
var someSymbolSprite:Sprite = Sprite(new someSymbolClass());
addChild(sprite);
}
}
}
How can I get all of the definitions in a SWF, without specifying each explicitly?
As of Flash Player 11.3, you can use ApplicationDomain.getQualifiedDefinitionNames().
See the official documentation for the method and this blog post about the Flash Player release.
EDIT: This is the quickest solution to your problem : http://www.bytearray.org/?p=175
Hi, you could use this library : https://github.com/claus/as3swf/wiki/
Don't have the time to do deeper test, but here is what i found :
1 - I have created a .swf containing in the library 2 exported MC, $Test and $Test2
2 - Once the .swf loaded by a Loader, i run this code :
var swf : SWF = new SWF(loader.contentLoaderInfo.bytes);
trace(swf);
3 - In the output you'll notice theses lines :
[76:SymbolClass]
Symbols:
[0] TagID: 2, Name: $Test2
[1] TagID: 1, Name: $Test
I think that there is a way to obtain this info directly thru the library API
You have to put the loaded SWF in the current ApplicationDomain.
Use ApplicationDomain.currentDomain to do that, on the ContextLoader info.
loader.load(request, new ContextLoader(false, ApplicationDomain.currentDomain));
It should work.
Following from the answer I received from a previous question I asked here a few days ago (it's about SWC , but in your case, it doesn't really make a difference )
Working with SWCs - getDefinitionByName issue
If both SWFs share the same ApplicationDomain, you should be able to access the loaded SWF classes directly by doing this:
//provided that SomeSymbol extends Sprite...
var someSymbolSprite:Sprite =new SomeSymbol();
On the other hand, you won't be able to do this
var SomeSymbol:Class = getDefinitionByName("SomeSymbol");
unless you create a library of objects from the loaded SWF
var ssym:SomeSymbol;
Check the above link for more details.

Clearing eventListeners on a FileReference object

I have a strange issue! I am trying to remove an event listener on a FileReference object by calling a function, but it seems not to be removed, and I do not understand why.
Here is the code:
private function clearFileUploadListeners(file:FileReference, index:String):void {
var dispatchEvent:Function = function(event:Event):void {
dispatch(event.type, event, index);
};
file.removeEventListener(Event.COMPLETE, dispatchEvent);
var bool:Boolean = file.hasEventListener(Event.COMPLETE);
if (bool)
trace("ERROR");
}
When I run this code, the trace actually happens. I don't understand why this boolean returns true, when I just tried to remove the eventListener just above! I guess I am probably doing something really stupid because it seems like a strange error.
I hope someone can please help me on this issue.
EDIT:
I believe it has to do with the fact that the dispatchEvent function is defined inside another function when I add the listener:
private function upload(file:FileReference, index:String):void {
var dispatchEvent:Function = function(event:Event):void {
dispatch(event.type, event, index);
};
file.addEventListener(Event.COMPLETE, dispatchEvent);
}
The problem is that I need to access this "index" variable from the listener, and I can't set it as a global variable as each file has it's own index and it's a burden if I have to extend each event class to keep track of the index (Event, ProgressEvent, ..). I hope someone can please help me on this.
EDIT2:
I actually found a temporary solution, I am not sure if it is the best! I put my removeListener method actually inside the upload method, but made it a variable. As AS3 allows dynamic object, I attached this method to one of my object, and so I just call the reference to the method when necessary. The event is actually removed. Is this a good solution please?
Thank you very much,
Rudy
You're right, it has to do with the fact that you're defining a function inside another function, then using it to handle events.
Each time the function upload is called, it creates a new closure, and assigns a reference to it to the dispatchEvent variable, which is then passed to the addEventListener class. So each time upload is called, it is using a new, different closure in the call to addEventListener. Similarly, in the clearFileUploadListeners function, a new closure is being created on each call (which happens to have the same code each time, but isn't the same function object). The call to removeEventListener does nothing if the given callback has not been added as an event listener for the given event, which is the case here.
To solve your problem, you need to store a reference to the closure that you pass to the addEventListener function. This way, you can get a reference to the same closure that was added when you need to remove it later in clearFileUploadListeners.
You can try something along the lines of the following code (untested):
import flash.utils.Dictionary;
var callbackRegistry:* = new Dictionary();
private function upload(file:FileReference, index:String):void {
var dispatchEvent:Function = generateFileUploadCompleteCallback();
callbackRegistry[file] = dispatchEvent;
file.addEventListener(Event.COMPLETE, dispatchEvent);
}
private function clearFileUploadListeners(file:FileReference, index:String):void {
var dispatchEvent:Function = callbackRegistry[file];
callbackRegistry[file] = null;
file.removeEventListener(Event.COMPLETE, dispatchEvent);
var bool:Boolean = file.hasEventListener(Event.COMPLETE);
if (bool)
trace("ERROR");
else
trace("YAY, ALL OK!");
}
private function generateFileUploadCompleteCallback(index:String):Function {
return function(event:Event):void {
dispatch(event.type, event, index);
};
}
Two other things to note on this subject.
If you must utilize a native Event directly then you should pretty much always make sure and use these last three optional params :
myObject.addEventListener( Event.COMPLETE, myFunction, false, 0, true );
Check Grant Skinner's post on the subject here :
http://gskinner.com/blog/archives/2006/07/as3_weakly_refe.html
And the very best practice of all is to ALWAYS (seriously always) use Robert Penner's Signals (instead of custom events) and his NativeSignals (to wrap needed native Flash events).
Five times faster than Flash's native events.
Always safe with weak references.
Any number of typed payload(s) in each Signal.
Get the SWC here :
https://github.com/robertpenner/as3-signals
Signals were designed to solve the very problem you are having.
Imagine instead of creating an array and managing that to remove all listeners if you could just call :
signalBtnClicked.removeAll();
or
signalBtnClicked.addOnce( function( e : MouseEvent ) : void { /* do stuff */ } );
Knowing that the closure you just created will immediately be dereferenced once it is called and happily go night night when the GC makes its rounds.

External SWF Loading problem

I have an SWF loading in an SWF containing a papervision scene.
I've done it before yet problem is, I get an error - I'm not sure what the issue really is.
private function downloadSWF(url:String):void
{
trace(url);
var urlRequest:URLRequest = new URLRequest(url);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loaderProgressEventHandler);
loader.load(urlRequest);
}
private function loaderProgressEventHandler(ev:ProgressEvent):void
{
loader.preloaderCircle.percent = ev.bytesLoaded / ev.bytesTotal;
}
When the application runs the code - I get the error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at com.dehash.pv3d.examples.physics::WowDemo()
Why am I getting this if the loading hasn't even complete yet?
Thanks in advance guys.
Edit: Try a blank child swf, see if the other one was trying access something in the parent. – Jorge
I did this, it seems, even with a simple SWF with a mouse click listener causes the Error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at simple_fla::MainTimeline/frame1()
My code for that is:
import flash.events.MouseEvent;
this.stage.addEventListener(MouseEvent.CLICK, onClick);
function onClick(ev:MouseEvent):void
{
trace("MouseClick");
}
Am I missing something blatantly obvious??
The problem is that the loaded swf starts running without it being added to the stage. So stage is null, resulting in that error.
The second example with the addedToStageEventHandler works because there stage is only referenced after the object was added to the stage, so stage is not null anymore.
A possible solution for the first error is adding the loader to the stage. That way, when the swf is loaded and starts, it already has a stage reference.
It won't even load if there's an error. You're accessing an unreferenced object on the WowDemo() class...did you instantiate correctly the class?
this seems to work inside my child SWF:
this.addEventListener(Event.ADDED_TO_STAGE, addedToStageEventHandler);
function onClick(ev:MouseEvent):void
{
trace("MouseClick");
var event:Event = new Event("END", true, false);
this.dispatchEvent(event);
}
function addedToStageEventHandler(ev:Event):void
{
this.stage.addEventListener(MouseEvent.CLICK, onClick);
}
does anyone know Why?