ActionScript operator as - actionscript-3

does anybody have a good explanation of the as operator?
On one hand it seems to me, that it is often better to use as instead of instantiating a new object.
But then there are situations, when this operator let's me down. For example when loading a text file in XML format through an URLLoader:
private function completeHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
trace("completeHandler: " + loader.data);
var x:XML = new XML(loader.data);
trace("x=" + x);
}
Why do I have to use a constructor here? Why can't I say var x:XML = loader.data as XML; and save some memory?
Thank you for any insights!
Alex

as evaluates whether a variable's type is a super class or subclass of another class. It does not create a new object. The difference to is being that while is returns a Boolean value, as returns either an object of the desired type, or null. It is used for type casts.
See the ActionScript documentation.
A typical use case would be using a MovieClip on the stage, which is retrieved by instance name:
// This will not compile:
var d:DisplayObject = stage.getChildByName ("instance1");
d.gotoAndPlay (2);
// This will play the MovieClip from frame 2
var m : MovieClip = stage.getChildByName ("instance1") as MovieClip;
m.gotoAndPlay (2);
stage.getChildByName() always returns a DisplayObject, regardless if it's really a MovieClip, Sprite, Button, etc. So if you want to use any of class MovieClip's methods, you need to type cast to MovieClip first. This does not, however, create a new MovieClip but simply ensures that you are using the correct type.

Related

AS3 MovieClip name ambiguity

Summary: I create instances of various MovieClips via AS3, using MovieClip class objects that are defined in the library.
As each MC is instantiated, I push it into an array for later reference.
Finally I create an XML file that contains data related to each MC, including its name. This is the problematic part – the name has to be able to identify the respective MC when the XML is read back in. I don’t want “instance17” etc, which I assume will be meaningless in another session.
Background: I am not a career OO programmer and this is a temporary assignment, forming only a very small part of my long-term interests. It will probably be a couple of years before my next Flash project.
Create instance
Library object
Type: MovieClip, linkage _brakepipe
Instantiation
var brakepipe: _brakepipe = new _brakepipe();
shapes.push(brakepipe);
Then later
var clip: MovieClip = shapes(i);
Trace (clip);
This yields
[object _breakpipe]
So it is giving me the class name, not the MC instance name. What property or method of MC would yield “breakpipe”? (Or even "_breakpipe" - without the "object" prefix?)
You can use an associative array. It could look like this:
var shapes:Array = new Array();
and then
shapes.push({item:_brakepipe,_name:"brakepipe"};
Essentially the curly brackets create an Object instance and the name before the colon (:) is the name you create that you want associated with the value after the colon.
so now you can do this in a loop
trace(shapes[i]._name+"\n"+shapes[i].item);
// output:
// brakepipe
// [object _brakepipe]
The nice thing about this method is you can extend it for any number of properties you want to associate with your array element, like this:
shapes.push({item:_brakepipe,_name:"brakepipe",urlLink:"http://www.sierra.com",_status:"used",_flagged:"false"};
and now
shapes[i]._status
would return the string "used". And you could change that value at runtime to "new" by doing
shapes[i]._status = "new";
The Instantiation / Then later / This yields... Seems to be unclear for me, but you may try this and change the code...
Because I'm not sure not sure about the instance name you want to store...
In your loop you may do this if clip is a MovieClip! :
var clip: MovieClip = shapes(i);
clip.name = "breakpipe_" + i
trace (clip.name);
// will output : breakpipe_1 - > breakpipe_n...
You may deal with the clip.name later by removing the extra "_number" if you want.
If i == 13
var clip: MovieClip = new MovieClip();
clip.name = "breakpipe_" + 13
trace(clip.name);
// output breakpipe_13
var pattern:RegExp = /_\d*/g;
trace(clip.name.replace(pattern,""));
//output :
//breakpipe
So here, you may push your Array or Vector with the instance name.
Am I wrong?

ActionScript 3 - use [brackets] instead of getChildByName

I have a MovieClip inside library, linkaged to MyObject and it contains a textField.
I don't know how I can access this textField without using the getChildByName method.
Apparently, the 3rd section works when object is on stage (without using addChild). But when using addChild I think there has to be some kind of casting; which I don't know how.
var childElement: MyObject = new MyObject();
childElement.name = "theChildElement";
container.addChild(childElement);
btn.addEventListener(MouseEvent.CLICK, changeText);
function changeText(event: MouseEvent): void
{
var targetBox:MovieClip = container.getChildByName(childElement.name) as MovieClip;
targetBox.textField.text = "hello"; // THIS WORKS
// This works too:
// MovieClip(container.getChildByName("theChildElement"))["textField"].text = "hello"; // THIS WORKS TOO.
// THIS DOESN'T WORK. why?
// container["theChildElement"]["textField"].text = "hello";
}
As confusing as it may seem, instance name, and name are not the same. From your code you should always be able to get to your MC by it's variable name. To get your last like to work you could just use this.
childElement["textField"].text = "hello";
There is a difference between Symbols created by the Flash IDE, which aggregate other DisplayObjects and programmatically created DisplayObjects.
When a DisplayObject is created in the Flash IDE, it's instance name can be used to resolve the instance as a property - which means it can be accessed via []. The [] can be used to access properties or keys of dynamic declared classes - like MovieClip. This necessary because you'll most likely down cast to MovieClip instead of using the symbol class created by Flash. That is not possible when simply using addChild, addChildAt or setChildAt from the DisplayObjectContainer API.
It is always the save way to access it via getChildByNameand check for null because otherwise your app, website or whatever is doomed for 1009 errors as soon as someone is changing the symbols.
I'd create a bunch of helper methods, like
// not tested
function getChildIn(parent:DisplayObjectContainer, names:Array):DisplayObject {
var child:DisplayObject, name:String;
while (names.length > 0) {
name = names.shift();
child = parent.getChildByName(name);
if (!child) {
// log it
return null;
}
if (names.length == 0) {
return child;
}
}
// log it
return null;
}
function getTextFieldIn(parent:DisplayObjectContainer, names:Array):TextField {
return getChildIn(parent, names) as TextField;
}
function getMovieClipIn(parent:DisplayObjectContainer, names:Array):MovieClip {
return getChildIn(parent, names) as MovieClip;
}
Your third method doesn't work because you are trying to call the ChildElement by it's name
without using getChildByName method. On the other hand, you shouldn't call your textField textField, because that's already an actionScript property.
Your should rather call it 'displayText' for example.
For a textField called 'displayText' contained in childElement :
function changeText(event:MouseEvent): void
{
childElement.displayText.text = "hello";
}

Why aren't properties reset when object is re-cast as original type?

I tried to ask this question here, but couldnot get a satisfactory answer. (Why should compiler allow super-class of a parameter in a function)
Trying to ask again.
Why casting, doesnot loose the member functions, when done on classes ? In the following, i expected, that after casting to Sprite, the class should loose all it's information regarding the current frame. But it retains the information, as if casting is just a "show-off", not "actually done" internally ?
import flash.display.MovieClip;
import flash.display.Sprite;
var mc:MovieClip
mc.gotoAndStop(2);
trace(mc.currentFrame); // output 2 --> that's ok
var sprite:Sprite = Sprite(mc)
trace( MovieClip(sprite).currentFrame);//output 2, value not lost, which is questionable
Output:
2
2
I know, the answer can be, it's how Adobe did it. But what's the logic ? Ideal logic should be that, after casting, and recasting, all the values must be restored to default. ( '0' in this case )
V.
Cast will not clear the member fields. Casting show what others can access
from this object but not change the object.
In flash objects are passed by reference. Imagine you have a object in memory ( mc in your case ). When you create sprite by casting the mc you pass the reference ( memory address ) to sprite var. At this point mc and sprite points to same address in memory. When you cast sprite to MovieClip you pass same address from mc. And this address is address for MovieClip mc at this point currentFrame will access the value of mc. Casting is not like copy constructors
Edit.
By using this link I create simple code that proove my words:
var memoryHash:String;
var mc: MovieClip = new MovieClip();
var s: Sprite = Sprite( mc );
try
{
FakeClass(mc);
}
catch (e:Error)
{
memoryHash = String(e).replace(/.*([#|\$].*?) to .*$/gi, '$1');
}
trace( memoryHash );
try
{
FakeClass(s);
}
catch (e:Error)
{
memoryHash = String(e).replace(/.*([#|\$].*?) to .*$/gi, '$1');
}
trace( memoryHash );
And the Fake class:
package {
public class FakeClass {
public function FakeClass() {}
}
}
The output will show the memory address of mc and s. As you can see thay are equal. In my mashine the output is
#35ed041
#35ed041
I'm not sure what you're trying to do here, but things like MovieClip(sprite).currentFrame are obviously going to lead to weird results. Because you're casting your sprite as a movieclip, it will have a currentframe. Try doing currentFrame on a sprite and see what happens.

How to run MovieClip ( who is an external swf ) function from flex

I try to call swf function ( setPoints(nr:int):void; ) from flex.
[Embed(source="img/anim/x2.swf")]
[Bindable]
public static var points:Class;
public function strikeAnimation(area:SpriteVisualElement, strike:int):void{
var mc:MovieClip = new points() as MovieClip;
area.addChild(mc);
//how to run?
area.mc.setpoints(strike);
}
Any ideas?
I tried call function like this -
area.getChildIndex(area.getChildIndex(mc)).setpoints(strike);
The reason you received an error with the line of code above is that getChildIndex expects a DisplayObject and returns an Integer.
So, this probably worked:
area.getChildIndex(mc)
But, it returned an integer which you can't use as the input to another getChildIndex call because an integer is not the same as a child.
Something like this should get you an instance of your child:
var myChild :MovieClip = area.getChildAt(area.getChildIndex(mc))
However, the setpoints method is not a documented method of a movieclip; so to execute the setpoints method on your custom movie clip you're going to have to convert it to your custom type. Conceptually something like this:
(myChild as myCustomType).setpoints(strike);

AS2 to AS3 migration create empty movie clip with dynamic name

I am trying to migrate as2 to as3 code. The normal solution to my problem involves using the first parameter of the createEmptyMovieClip() as the name of your movie clip. In several instances I have a dynamic value for this first parameter- so my question is How should I go about doing this?
//my code
function someFunction (){
loader_mc = this.createEmptyMovieClip("text"+value, value);
value++;
//do stuff with it
}
//normal non-dynamic solution
function someFunction (){
var text:MovieClip = new MovieClip();
addChild(text);
//do stuff with it
}
In your question, you're already saving a direct reference to the MovieClip. If that's the only reference you need to do your work, then you really don't need to give the MovieClip a name.
If you do need the name, though, you can always assign the MovieClip a name after the fact:
var myClip:MovieClip = new MovieClip();
myClip.name = "text"+value;
parent.addChild(myClip);
This will let you use the getChildByName method:
parent.getChildByName("text"+value);