views:

1427

answers:

17

Guys, I am thoroughly surprised that there is no Flash Hidden Features post yet in the Hidden Features series that I've been tracking for a while now.

There is a recent AS3/Flex one but it's not very active and I don't exactly mean just AS3 when I say Flash here.

The Hidden Features series is great for people who are new to a certain language. It shows the ropes and certain valuable tricks, all in one place. I think it's a brilliant idea. Even experts sometimes find tricks they'd never heard about.

When I started with Flash, I was taken aback by the Flash IDE and odd concepts of Flash, compared to other programming languages.

So, here goes: what are some hidden features of Flash as a language (AS2/3) and the Flash IDE?

Let the fun begin.

+5  A: 
Graphics::drawRoundRectComplex (x:Number, y:Number, width:Number, height:Number, topLeftRadius:Number, topRightRadius:Number, bottomLeftRadius:Number, bottomRightRadius:Number) : void;

It's not documented anywhere, but a forum post explains more.

Can you document it here then?
Artem Russakovskii
+1  A: 

Its not really hidden (very obscured in the documentation), but updateAfterEvent is quite an unknown and useful method under certain circumstances...

Cay
+2  A: 

ActionScript 2

every class is a function and every function a class ... AS2 is prototype based ...

trace.prototype = { };
var f = trace;
trace(new f());//will yield [object Object]

accessing Function::prototype allows extending classes at runtime:

MovieClip.prototype.moo = function () {
    trace(this+" says 'moooooooo' ...");
}
_root.moo();//_level0 says 'moooooooo' ...


Object::__proto__ ... allows you to change the prototype of an object, which can be used for runtime reclassing:

var o = trace;
o.__proto__ = [];
trace(o.push("foo", "bar", "foobar"));//3 here
trace(o.length);//also 3
trace(o[1]);//bar

in this example, the function trace is reclassed to Array ... pretty cool, huh? :)


Function::apply and Function::call allow applying any function as a method to any object:

Array.prototype.push.apply(trace,[1,2,3]);
trace(trace.length);//3
trace(Array.prototype.splice.call(trace, 1,1));//2 ... actually, this is [2] (the array containing 2)


using the three above, instantiation of a class MyClass with parameters param_1, ..., param_n can be written as:

var instance = {};
instance.__proto__ = MyClass.prototype;
MyClass.call(instance, param_1, ..., param_n);


a corelation of Function::push and Function::apply is that this is simply a function argument, that is passed automatically ... as any other function argument, it can be written to ...

var f:Function = function () {
    this = [];
    this.push(1,2,3);
    trace(this);//1,2,3
    this = _root;
    trace(this);//_level0
}
f();

Object::__resolve ... settings this method allows you to react to lookups on undefined properties ... this is fun and useful for proxying, mocking, composition, delegation, and so on ...

import mx.utils.Delegate;

var jack:Carpenter = ...
var jim:BlackSmith = ...
...
var guys:Array = [jack, jim, ...]
var o = { __resolve : function (name:String) {
    for (var i:Number = 0; i < guys.length; i++) {
     var guy = guys[i];
     if (guy.hasOwnProperty(name)) {
      var ret = guy[name];
      if (ret instanceof Function) {
       ret = Delegate.create(guy, return);
      }
      return return;
     }
    }
    return "sorry man, but nobody knows, what '" + name + "' means";
});

//some really imaginary stuff (i hope it makes the point):
trace(o.saw);//[object Hammer]
trace(o.anvil);//[object Anvil]
trace(o.ventilator);//"sorry man, but nobody knows, what 'ventilator' means"
trace(o.makeSword());//[object Sword]


that's it for now ... there's an awfull lot more ... the thing is simply, that AS2 is an exiting language, but painfully slow ... AS3 in comparison is boring as hell, but the speed increase is really great ...

back2dos
+1  A: 

[AS3]

The || (logical or) operator can be used for any truthy/falsey values.

var obj : Object = nullObject || instance; // instance
var val : int = 5 || 10; // 5
var val : int = 0 || 10; // 10

Also, you can use & and | (bitwise and/or) to do a non-short-circuted expression:

function functionA() { return false; }
function functionB() { return true; }

if (functionA() && functionB()) { trace("something"); } // methodB won't be executed
if (functionA() & functionB()) { trace("something"); } // methodB WILL be executed
Richard Szalay
+1  A: 

[AS3]

I wouldn't necessarily call this a 'feature', but you can actually access variables before they are defined (even with strict compilation) due to the way the compiler works:

trace(hb); // null
var hb : HBox = new HBox;
trace(hb); // [object]

It can actually lead to frustration when refactoring code (since it compiles).

Richard Szalay
+2  A: 

[AS3]

When looking for a the value of a variable, the player will run up the scope chain until it finds what it's looking for. So using nested (anonymous) functions you do things like make asynchronous calls and handle it using variables that were defined on the scope of the calling method. e.g.

function loadData(myAwesomeObject : AwesomeObject) : void
{

   var urlLoader : URLLoader = new URLLoader();
   urlLoader.addEventListener(Event.COMPLETE, function(event : Event) : void
   {
      myAwesomeObject.someReallyAwesomeMethod(event.target);
   });
   urlLoader.load(new URLRequest("http://someService"));

}

Loads of other uses for this and it's really very useful

James Hay
Anonymous functions will screw up debugging since they are not part of a helpful scope chain. Plus, they are really hard to read and make maintenance a chore.
Tim B.
They most certainly do not screw up debugging. You can step through an anonymous function no problem. Plus the addition of an extra scope level when used properly is a helpful construct. So long as they are succinct in their contents they are not hard to read. Granted a hundred line anonymous function is wrong. 5-10 lines of code is perfectly readable and mainatinable.
James Hay
@Tim B - I'm far from Adobe's biggest fan, but your misunderstanding of closures hardly equates to them "screwing up" debugging.
Richard Szalay
After 2 years of supporting an application rife with anonymous functions, I disagree with these 2 responses. When the debugger/logger spits out <anonymous> in the scope chain, I have no clue where the failure is. I consider that a "screw up", as in "the developer screwed up my life with his shortcut."To me, anonymous functions create more headaches than solutions. My opinion is based on experience, not misunderstanding.
Tim B.
@Tim B - The method stack always contains the method from which the anonymous method was called and can be navigated to in within the FB debugger. I don't doubt that you've seen misuse of closures, but any feature can be misused.
Richard Szalay
@Tim B - Used properly the extra scope is a tool not a 'shortcut'. When it's used for the purpose it was designed for it's extremely powerful. Like Richard Szalay said all programing constructs can be misused... looks like you got the raw end of the deal in having to maintain badly written code!
James Hay
Fair enough, I have developed a deep mistrust of this kind of coding approach and avoid it.
Tim B.
+4  A: 

[Flash IDE]

This isn't a feature as much as it is a gotcha. When specifying a document class for an FLA, the compiler does not subclass that class, it modifies it.

This can cause problems when you have several SWFs with the same document class, all being loaded into another SWF (since two classes with the same name cannot be loaded side-by-side into the same application domain). It results in the first being loaded and the second using the first's modified class, producing weird errors (as you can imagine).

The solution is either:

  • Create a proxy class for each FLA that subclasses the document class
  • Load each SWF into a new child application domain
Richard Szalay
oh.. I see this is the correct answer! 8P
dome
+1  A: 

[Flash IDE]

When you export a MovieClip as a swc you can add it to the components panel of by dropping it into the folder

C:\Documents and Settings\USER_NAME\Local Settings\Application Data\Adobe\Flash CS3\en\Configuration\Components\SOME_COMPONENT_FOLDER

Restart flash and it'll be in the components panel for you to use.

James Hay
Vista/7 don't call it "Documents and Settings". %userprofile%\Local Settings\Application Data\Adobe\Flash CS3\en\Configuration\Components\SOME_COMPONENT_FOLDER will work for all versions.
Richard Szalay
+4  A: 

MovieClip.addFrameScript() is a undocumented ActionScript 3.0 feature that allows you to specify a function that is called when the playhead of the Movieclip timeline enters a particular frame number.

function someFunction():void {

}

movieclip_mc.addFrameScript(4,someFunction);

The frame number is zero based (1st frame = 0) and needs to be whole numbers only, however if you wanted to use frame labels you could use something like this:

function addFrameLabelScript(frame:String, func:Function):void{
    var labels:Array = currentLabels;
    for(var i:int=0;i<labels.length;i++){
     if(labels[i].name == frame){
      addFrameScript(labels[i].frame-1,func);
     }
    }
}
Shrill
A: 

Custom metadata is something that isn't well documented or or promoted, but it s very helpful - without modifying a variable or changing its namespace, you can give it custom annotations similar to the way that you can in Java.

It is gone over in depth by Christophe Conraets on his blog

The simplicity of it is that you can put all of your own metadata, and then you just use describeType() and you will see all of your custom metadata at run time :)

wb2nd
+2  A: 

[AS3]

When you use the trace statement in AS3 you can pass in multiple parameters and AS3 will format the output so that there is a space between each.

trace("Hello","World");

would output "Hello World".

AS2 does not support multiple parameters for trace so you are forced to do something like

trace("Hello "+"World");
Allan
A: 

Well this might not be a hidden feature but maybe people have missed that there are external tweening engines you can use. My latest favourite is Greensocks. The only thing in my opinion it has lacked seems to be improving, workflow. Have not tested v.11 yet but definitely will on my next AS project: http://blog.greensock.com/v11beta/

amoeba
You can't touch tweenlite, I'm just a little concerned about the license. Tweensy is also very good/fast.
PiPeep
+1  A: 

You can create weak references in ActionScript3 by using the Dictionary object.

gmj
+7  A: 

[AS3] Tips for working with arrays or Vectors

Fastest way through an array, always from the back

var i:int = array.length;
var item:Object;
while(i--)
{
   item = array[i];
}

Clearing an array,

//faster than array = []
array.length = 0;

//garbage friendly
while(array.length)
{
    array.pop();
}

Pushing and splicing

//faster than array.push();
array[array.length] = "pushed value";

//faster than splice(index, 1)
var index:int = array.indexOf(splicee);
array[index] = null;
array.splice(array.length, 1);

Cloning

//fastest way to clone
var newArray:Array = array.concat();

//fastest manipulation
var mapFunction:Function = function(item:Object, index:int, source:Array):Object
{
    return //your cloning or morphing here
}
var newArray:Array = array.map(mapFunction);
A: 

Not exactly hidden, but what about the often overlooked "include" macro (yes, it still exists in as3)? - very useful for faking multiple inheritance (when used side by side with an interface), even if it usually is a bad practice.

PiPeep
+1  A: 

when using flashvars write a utility method getFlashVars().

function getFlashVars():Object {
return Object(LoaderInfo(this.loaderInfo).parameters);

}

then when I'm coding I always add an extra || so that I won't have to flashvars while debugging.

localVar = getFlashVars().sampleVar || "default.xml";
zero juan
+1  A: 

I'm sure you will find usefull this article by jpauclair: AS3 hidden treasure in the mm.cfg file

Ismaelj