Showing posts with label Adobe Flash. Show all posts
Showing posts with label Adobe Flash. Show all posts

Saturday, June 27, 2009

Flash AS3 Dictionary - bliss!

I came in on ActionScript at version 3, and with a strong javascript and .NET background.

Compared to javascript (which I quite like), I think ActionScript is even better. (They both have major issues, but I still quite like them, even if I hate the Flash software development tools which are "crappy as"...)

Sometimes you need to iterate a set of ActionScript object instances, and keep a record of some piece of data for each object instance.

In javascript it's easy - just add a new dynamic data field to each object instance.

But ActionScript adds the concept of "sealed" classes, which prevent the dynamic addition of new data fields.

So we're stuffed?

Well, there is a solution. Only one, but it works very well.

It's the new ActionScript 3 Dictionary.

It is an associative array keyed not by a string but by an object instance.

I use Dictionary objects all the time in other languages, so I was hoping ActionScript might have one, and I finally went looking for it, and found it yesterday.

Here are two articles I felt did a great job of introducing this powerful Dictionary object :

Viva la Dictionary!

Microsoft Silverlight stumbles at the gate

I have in the past predicted that Adobe Flash will lose out to Microsoft Silverlight.

But Microsoft keeps slipping up in one key area : ubiquity.

Silverlight was supposedly a technology that would run everywhere - including on mobile devices.

But Microsoft can't even get Silverlight running on their own Windows Mobile platform, let alone any other mobile devices.

On the other hand, Flash has Flash Lite, which is already on millions of handheld devices worldwide.

Yes, the Microsoft development tools actually work reliably, and yes, the Flash development tools are riddled with bugs, poorly documented, and priced uncompetitively.

But with the meteoric rise of handheld devices, and the lack of Silverlight support for any handheld devices (despite announcements over the past two years or so that "it's coming"), Microsoft is giving Adobe a massive breather.

A breather that may cost Microsoft years in their attempt to dominate this particular market.

If Adobe would make their tools and documentation at least as good as Microsoft's, then they could justify their price structure, and leave few incentives for anyone to use Silverlight.

But on the other hand, if Adobe continues to prove incompetent in QC for software development tools and documentation, and Microsoft finally gets their act together with the long-promised and I'm-growing-tired-of-waiting-for "Silverlight for mobile", then my original prediction stands, and Silverlight will move out of the realm of predominantly line-of-business apps, more and more into the mainstream, until the days of Adobe's dominance are a distant memory like the Commodore 64.

Tuesday, May 19, 2009

Automate Adobe Flash using VB.NET or C#

Adobe is very thin as usual on technical details, so I've had to poke around and try different things.

Here's what I've found :

* .NET can communicate directly with Illustrator, but not directly with Flash, nor with BridgeTalk.

* .NET can send javascript to Illustrator, including javascript which utilises BridgeTalk to communicate between Illustrator and Flash.

* So it is possible to automate both Illustrator and Flash using VB.NET/C#/other-.NET-languages, but it requires .NET <-> Illustrator <-> BridgeTalk <-> Flash.

* In VB.NET, you connect to Illustrator as follows :

Dim app As Object = CreateObject("Illustrator.Application")

* To get Illustrator to run arbitrary javascript :

app.DoJavaScript(myJavaScript);

e.g. to get Illustrator to greet us :

app.DoJavaScript("alert('Hello!');");

* To get Illustrator to return a useful value from a script we have sent it, don't use the "return" keyword - just include the return value as the final expression in the script block.

e.g. :

Dim ReturnValueFromIllustrator As Object = app.DoJavaScript("1 + 2;")
MsgBox(ReturnValueFromIllustrator) ' Shows "3"

* The .NET <-> Illustrator leg is synchronous, even though the Illustrator <-> BridgeTalk <-> Flash legs are ASYNCHRONOUS. (Yeah - just to make life more interesting.)

Hmmm - in short, I wouldn't say it's "easy", but it is possible.

Maybe Adobe will enter the 21st century sometime and really make all their apps easily cross-scriptable, and their scripting engines a lot more robust. Until then...

... your brother in the pain of scripting Adobe products.



P.S. If you're using C#, or if you're using VB.NET and want a better Intellisense experience (and better runtime performance, and better compile-time checking) than just using VB.NET's CreateObject method, add a reference to the "Adobe Illustrator CS4 Type Library". Once you've done that, you can connect to Adobe Illustrator as simply as "Dim app As New Illustrator.Application" (or in C#, "Illustrator.Application app = new Illustrator.Application();").

Thursday, May 14, 2009

Cross-scripting Adobe Illustrator and Adobe Flash

21st century, expensive products, same company makes them all, and sells them all in the same package.

You'd think they'd play happily together.

And Adobe documentation here and there hints that they do.

But finding out how is mighty difficult.

You fire up the ExtendScript Toolkit, and the documentation makes it sound like you can do almost anything from there.

Play around with Adobe Illustrator scripting in the ExtendScript Toolkit - sweet!

But now try to script Adobe Flash...

... oops, um, well, there doesn't really seem to be a way to do it.

Does Adobe document that you can't? Well, not that I've managed to find.

In fact, one other commentator stopped short of giving a definitive answer that Flash isn't supported by the ExtendScript Toolkit, and instead just said that it seems it isn't.

C'mon Adobe, give us clear, informative, unambiguous documentation!

In fact, if you put "#target flash" in a script in the ExtendScript Toolkit, and try to run it, it actually launches Flash, and then tells you that it failed to connect to the Flash scripting engine. What the???

An Adobe brochure about Flash CS3 claims that it is now compatible with ExtendScript, but frankly, I don't see how, and we're now up to CS4!!! ("Flash CS3 also adds ExtendScript and BridgeTalk support for cross-application scripting.")

So after many hours of wasted time, I've figured out how to make Illustrator and Flash sing to each other.

I'm not impressed by the obtuse steps required.

And I'm not impressed by the extremely non-definitive documentation on Adobe's part.

Here's how you do it :

1) Your Adobe Illustrator scripts will be written using the ExtendScript language, whereas your Adobe Flash scripts must be written using a language called JSFL. Both languages are javascript-based, and have many similarities, but they also have many differences. (e.g. native filesystem access in ExtendScript is done via the File class, whereas in JSFL it's done via the FLfile class. Hello, any reason for that, anybody?)

2) Adobe Bridge is not Adobe BridgeTalk. The names are very similar, but the use is very different, and unfortunately, the difference is not clearly articulated in Adobe docs.

Adobe Bridge is a moderately useless file cataloging and file browsing tool.

In contrast, Adobe BridgeTalk is a simple but powerful inter-process communication tool.

So, we're going to use Adobe BridgeTalk to communicate between Illustrator and Flash.

3) It is very hard to find Adobe BridgeTalk documentation. (e.g. Google-ing for "adobe bridgetalk reference" is close to useless.)

I suspect this is in part because BridgeTalk is SO simple that there's hardly anything to document, and thus, Adobe is content to let developers learn by example.

And learn by example is how I had to do it.

4) One of the best sources of examples of Adobe BridgeTalk scripting is actually in the Adobe Bridge SDK. Yes, that sounds confusing, but it's true.

Download said Adobe Bridge SDK. It's about 4MB of compressed files. Unzip, and inside are a few interesting PDFs, and a bunch of jsx files showing cool tricks using BridgeTalk (amongst other things).

(I suggest you read the short section "Communicating with Other Applications" in the "Bridge CS4 JavaScript Guide.pdf" that comes in the docs folder in the Adobe Bridge SDK.)

5) In brief, BridgeTalk sends javascript as a string, from one application to another (e.g. Illustrator to Flash), and sends the value of the last-executed-statement in said script back to the calling application. It's a bit obtuse, but it's very powerful.

6) Note that BridgeTalk is ASYNCHRONOUS. And there is no synchronous mode. So you have to be patient with writing the extra code to handle breaking a single synchronous procedure into smaller asynchronous steps.

7) There is an extremely-poorly-documented means of launching ANY application via BridgeTalk. e.g. you can run a Windows batch file, or trigger your source code versioning system, or invoke a custom tool you wrote in a non-Adobe language. You can pretty much run anything you like.

It's based around a function called "system".

As with most Adobe stuff, this "system" function is extremely poorly documented.

The only way I've found to use it is to call app.system('command-line.exe bla bla'); from within Bridge.

So - get this - if you want to fire up a useful external program (e.g. source code control) from within a script that is automating Illustrator or Flash, you need to use BridgeTalk to send a script to Bridge, and the script you send to Bridge needs to include the app.system(<command-line>) invocation. Talk about convoluted!

But at least it works.

Oh - and app.system(...) is SYNCHRONOUS, unlike BridgeTalk which is ASYNCHRONOUS. Just to make sure your neurons are really getting a workout...

8) If you've understood everything to this point, and want a cool trick to make it much easier to generate lengthy scripts that get shared between different Adobe products, you can use the toSource() function, as described by Justin of Ajar Productions in an article entitled "Easy (and Readable) ExtendScript to JSFL Workflow".

Remember : JSFL = scripting the Flash* development ("authoring") environment, whilst ExtendScript is used e.g. for Illustrator. Justin's article covers writing an ExtendScript for Adobe Illustrator, that also uses BridgeTalk to get Flash to do some things, yet all within a single script file, and without much messy code. Very nice work, Justin!

(* Technically, JSFL is used for a few other products, not just Flash, but for my present purposes, it is accurate enough to say JSFL = scripting the Flash development environment.)



Conclusion?

Adobe makes things horribly painful to learn.

Oh - and to use. e.g. obtuse error messages.

But despite the pain along the way, you can actually accomplish a huge amount. If you have spare hair and a high pain threshold, you might find (as I am finding) that ExtendScript, JSFL and BridgeTalk are extremely rewarding tools to be able to use.

Wednesday, April 15, 2009

Flash, translate transform, and x/y co-ordinates

"Self Documenting Code" is my mantra - code that is intuitive.

Flash is not.

I lost yet another hour or two trying to get a simple translate transform working. The doco fails to mention that :

If you set x or y for a DisplayObject, it effectively overwrites any translate transform in the current transformation matrix for the DisplayObject.

I hate to be harsh, but you could at least mention this in the documentation! XAML transformations apply in addition to any x/y co-ordinates set on an object. Not so in Flash.

And so if you apply a transformation, and then set a DisplayObject's x/y properties, you might be puzzled wondering why the translation component of the transformation is not taking effect.

That's why.

It makes sense enough when you understand it, but it proves once again that Adobe is often worse than useless at writing documentation and at designing intuitive APIs. Why did I have to spend an hour or two figuring this out for myself? It should have been documented, or been more apparent in the API itself.

Thursday, April 9, 2009

Flash automatically merges shapes at compile time

Here be dragons.

Flash automatically combines shapes at compile time.

So if you were expecting to place two or more shapes on the stage and be able to access them via the stage's getChildAt method, you're in for an interesting time.

It's not as simple as "Flash combines all shapes into a single shape". It seems to work based on z-index.

Suppose you add two shapes to the stage, then add a textbox, then add a third shape.

You'll discover at runtime that the first two shapes have been merged into one, but the third has not.

If you play with the z-index ("send to back", "send to front") in the Flash IDE, you'll discover that the ONLY thing that controls whether or not two particular shapes get merged at compile time is whether or not they are neighbours in the z-index.

(Technically, they need to be part of the same unbroken sequence of shapes in the z-index, so for example if you add three shapes to the stage in succession, they will be combined into a single shape at compilation time, because they will appear one after the other in the z-index.)

Unfortunately, I failed to find any documentation which mentions this, or any other Flash developers having their plans thwarted by this 'feature'. So I hereby post my "here be dragons" flag.

The solution? If you NEED the shapes to be drawn in Flash (as opposed to drawn in ActionScript at runtime) and you NEED them to be separate shapes at runtime, then cut them out of your document and paste them into a temporary document, then paste one shape back, then create an off-stage dynamic text field (to form a z-index divider), then paste in the next shape, and so on, and so forth.

Of course, it should be very rare that you need to do this kind of thing, but I came across such an instance today, and lost several hours due to this seemingly undocumented 'feature'.

Monday, April 6, 2009

Flash vs SilverLight : SilverLight will win (my prediction)

I've been living in Adobe Flash / ActionScript land for the last few weeks, and there has been a very unexpected side-effect.

Today, when I was working in Microsoft Visual Studio again, it was a joy to use!

I always used to think Microsoft Visual Studio was HIDEOUSLY slow and inefficient - and it is - but after inflicting Adobe Flash on myself for a week and a half, Visual Studio seems absolutely awesome.

As yet another example of the sheer stupidity which pervades Adobe Flash and its implementation of ActionScript :

1) Grab a big Adobe Flash project - you know, one that takes ten seconds to build.
2) Open it in Flash CS4.
3) Press Ctrl+Enter to run it in test mode.
4) Close the runner.
5) Press Ctrl+Enter to run it again, as if you just wanted to check out one more thing.

Guess what?

Adobe Flash is so stupid, that it doesn't notice that nothing has changed since the last build, and so it rebuilds the project, wasting more time.

And it doesn't seem to have any incremental build either. If you have a large project, and change one tiny thing ANYWHERE in the project, you face the entire laborious build process once again.

On a fast (3ghz QuadCore) computer, I am finding Flash makes debugging a major chore by making tedious to iteratively change and test.

Visual Studio in contrast? Do a debug run, and it will build and run. Run again without changing anything? It knows it doesn't need to rebuild, so it starts instantly. Change anything? It supports incremental build to a certain extent.

It makes Adobe Flash look like it comes from the 90s, or earlier. Except, that it's actually Adobe Flash CS4 - the very latest and greatest in 2009. Ouch - that sucks.

Oh - and I thought Visual Studio was bad, because the incremental build is actually quite limited. Turns out, Flash seems to have no incremental build at all.

And don't talk about load times - I thought Visual Studio load times were bad. But after Flash, it feels zippy.

And today, Flash crashed on me literally, hmmm, about ten times. I mean, crashed, dead, have to restart the app, and sorry about any unsaved work. That kind of crash.

Visual Studio is INCREDIBLY inefficient, but at least it hardly ever crashes. And Flash's inefficiencies make Visual Studio look like a racecar.

Add to this the documentation errors and erroneous compiler errors that define Flash 10 with ActionScript 3, and you have the perfect recipe for the most imperfect program I ever imagined could wear the Adobe name.

If it were a house, the "for sale" sign out front would say "full of potential".

Translation : it needs a LOT of work.

My bet?

Adobe will drop the ball (or continue to drop the ball).

SilverLight will win.

And it will take roughly 8 to 10 years to happen.

Sunday, April 5, 2009

Flash SimpleButton, and MOUSE_OVER and MOUSE_OUT not firing

Adobe Flash documentation is often worse than useless. Useless would be "tells us nothing we didn't already know". WORSE than useless is "tells us information that is NOT correct, causing us to waste time".

Their flash.display.SimpleButton is the culprit once again.

I was dynamically generating SimpleButton instances in ActionScript 3, and adding MOUSE_OVER and MOUSE_OUT event handlers.

But the event handlers were never firing.

I reviewed the documentation - the SimpleButton definitely supports the MOUSE_OVER and MOUSE_OUT events.

I tried adding the event handlers to the flash.text.TextField instances which formed the button states, but that didn't work either - the events simply never ever fired.

I finally figured out what's going wrong. It's that SimpleButton constructor once again.

Here's what the doco says (false info - worse than useless) about the SimpleButton constructor :

Any or all of the display objects that represent the various button states can be set as parameters in the constructor.

ANY OR ALL ... CAN BE. In other words, it is OPTIONAL to set the various states using the constructor.

In a previous blog post, I noted that, despite the CLAIM that the constructor arguments are optional, the first argument is actually MANDATORY.

If you don't specify the first argument, the button never transitions between states, even if you set the states later using the upState, overState etc properties.

But if you DO specify the first argument, the up-and-over animation works correctly.

That was from that previous blog post.

Well, the new lesson for today's blog post is that in fact ALL FOUR arguments to the constructor are MANDATORY if you wish to get MOUSE_OVER and MOUSE_OUT events from the SimpleButton.

It doesn't make sense, and it makes mockery of their (poor as too often the case) documentation, and in fact makes mockery of Adobe's ability to design an intuitive API, but it is the case.

The one saving grace is that we can specify the SAME DisplayObject for all four constructor arguments. e.g.

var sb:SimpleButton = new SimpleButton(MySprite, MySprite, MySprite, MySprite);

(And of course, the other way you can do it is subclass SimpleButton and set the upState, overState etc properties in your own constructor. Basically, by the end of the constructor, those values must be set.)



As a final note, I was just about to paste the simple test code I whipped up, to make it extremely easy for you to reproduce my test results, but as I did so, Adobe Flash suddenly died on me and completely disappeared from the taskbar without even its usual "Adobe Flash just died" popup message.

All I can say is that I am disgusted with Adobe Flash - not only is the documentation often worse than useless, but the program itself is fragile, and crashes on me usually more than once per work day.

And this is Flash CS4 - their latest and greatest...

Thursday, April 2, 2009

Flash bugs: dynamic TextField and letterSpacing issue

I'm creating TextField instances in ActionScript, modeled after one TextField instance in the Flash UI designer.

There are two stupid problems.

Problem 1:

The first is that Flash is very forgetful.

Suppose I go :

tb.text = 'Some new text';

Just like that, key TextField settings are lost! Idiotic. Things like letterSpacing get reset to zero.

The solution (noted by others) is to :

var tf:flash.text.TextFormat = tb.getTextFormat();
tb.text = 'Some new text';
tb.setTextFormat(tf);

If that makes sense to anyone, I suppose there probably are airborne sows.

But it kinda does the trick. Kinda.

Enter: problem the second

If I'm doing all this with an embedded font, the aforesaid hack DOES NOT WORK.

At least, not without a bit more effort.

I had the original textbox, built in to the Flash stage. Let's call it tbOriginal.

Then I have my dynamic textboxes, modelled off the original.

tbCreatedAtRuntime.text = 'Some text here';
tbCreatedAtRuntime.setTextFormat(tbOriginal.getTextFormat());

Nice - does the trick, except that the letterSpacing is shot.

So I play with the letter spacing. I try all sorts of values.

tbCreatedAtRuntime.text = 'Some text here';
var tf:flash.text.TextFormat = tbOriginal.getTextFormat();
tf.letterSpacing = 0.55; /* I tried lots of different values here. */
tbCreatedAtRuntime.setTextFormat(tf);

The problem was that, regardless of what letterSpacing value I set, it would often make no difference whatsoever to the overall length of the string.

But it was weirder than that. Once I got down to about 0.54, the string length jumped down very significantly. It was like the letterSpacing had a very course rounding applied, such that there was only one "real" letterSpacing option per 0.5 increment of the letterSpacing value.

But I knew this couldn't be the total story, because the tbOriginal was using a letterSpacing of 0.75, and on screen it was longer than tbCreatedAtRuntime with letterSpacing around 0.5, and shorter than tbCreatedAtRuntime with letterSpacing around 1, and as stated earlier, tbCreatedAtRuntime would treat letterSpacing of 0.75 the same as letterSpacing of 1.0.

What gives?

Fortunately, whilst not intuitive (after all, this is Flash isn't it?), the documentation did this time give me the clue I needed.

It turns out that Flash only supports integer values(1) for letterSpacing for "device fonts". My brain whirred away for a microsecond and I realised what the problem was.

I was using a special font, but I hadn't explicitly told my dynamically-created TextField to use font embedding. I just presumed that, since it got its TextFormat from tbOriginal, it would get the same font embedding as tbOriginal. Not so.

So now I explicitly tell tbCreatedAtRuntime to use the same font embedding as tbOriginal :

tbCreatedAtRuntime.embedFonts = tbOriginal.embedFonts;

... and now at last, letterSpacing works as expected. Whew!




But can you permit me to lament once more just how STUPID this design (or lack of design) is?

Adobe might be good at graphics, but they are very bad at development tools and APIs.

What SHOULD happen is that if ANY text field ANYWHERE in the Flash file has embedded a font, and ANY other text field anywhere else in the same movie (or even created dynamically) attempts to use the same font, the embedded font should be automatically applied to that other text field.

Now, failing that, at the very least, copying the TextFormat from one text field to another should ensure that if the first had an embedded font, the second uses the same embedded font.

Adobe, lift your game! Microsoft's APIs make yours look pathetic. You can do better than this!

(1) The integer-letter-spacing-for-device-fonts limitation is mentioned in the Flash 8 documentation. I'm using Flash 10, and I am surmising that Flash 10 supports 0.5 increments, in contrast to the Flash 8 doco which claims only 1.0 increments are supported in Flash 8.

Flash bugs: dynamic SimpleButton gotcha

I'm creating a SimpleButton in ActionScript and it ain't showing up.

var b:flash.display.SimpleButton = new flash.display.SimpleButton();
b.upState = bla;
b.overState = bla;
b.downState = bla;
b.hitTestState = bla;
b.useHandCursor = true;
this.addChild(b);

The problem is, the button, she no appear. Nada.

I thought maybe my problem is that I'm using the same sprite for the different states, but changing that didn't make any difference.

Turns out, Flash is proving its inferiority once again.

The SimpleButton constructor, it so happens, accepts four OPTIONAL arguments, being the four SimpleButton states.

Given that they are OPTIONAL, you would think you could omit them ALL and just set the four state properties after construction.

You'd think so. And so did I.

But it turns out that, even though the documentation and the in-editor code helps all say the states are optional, THE UP STATE IS ACTUALLY MANDATORY.

Ridiculous.

In short, this works, because it supplies the mandatory-though-pretending-to-be-optional UpState argument to the SimpleButton constructor :

var b:flash.display.SimpleButton = new flash.display.SimpleButton(bla);
/*b.upState = bla; - no longer needed*/
b.overState = bla;
b.downState = bla;
b.hitTestState = bla;
b.useHandCursor = true;
this.addChild(b);

And of course, you might prefer to just save lines and go :

var b:flash.display.SimpleButton = new flash.display.SimpleButton(bla, bla, bla, bla);
b.useHandCursor = true;
this.addChild(b);




On a related note, I was trying to figure out WHY Flash is so STUPID in this regard. (Stupidity and unintuitive behaviour are more common than I would have expected in ActionScript. I really honestly thought Microsoft's XAML was passable and that Adobe would be as good or better. Sadly, Adobe is actually far behind M$ in the 'we make things that actually make sense' game, even if M$ itself isn't perfect.)

My first guess was that the constructor determines the SimpleButton's dimensions from the upState, and thus, when no upState is passed to the constructor, the SimpleButton has no idea how big it needs to be.

If that were the case, I could simply set the SimpleButton's width and height, and it would work.

But no go.

Here's the code :

var b:flash.display.SimpleButton = new flash.display.SimpleButton();
b.width = 100;
b.height = 100;
b.upState = bla;
b.overState = bla;
b.downState = bla;
b.hitTestState = bla;
b.useHandCursor = true;
this.addChild(b);

And it is as dead and useless as the very first code listing in this article.

In short, it seems that the SimpleButton is COMPLETELY UNABLE TO HANDLE UPSTATE BEING OMITTED FROM THE CONSTRUCTOR INVOCATION.

Which makes me ask why Adobe's documentation is so poor that there is no comment about it. And why their compiler doesn't complain when that argument is missing from the constructor invocation. And in fact why, overall, they make such an unintuitive design.

Here's what I would have done, since I believe in making APIs as flexible as possible :

1) All constructor arguments are optional.

2) Button width and height are calculated just-in-time, or at least, calculation is deferred until upState gets set for the first time on a given SimpleButton instance.

Voila! Talk about intuitive! In contrast, I really don't know how Adobe muck up like this, and at multiple places throughout their API. Shame, Adobe. Shame. Please lift your game.

Sunday, March 29, 2009

Flash ain't so flash

I thought Microsoft SilverLight was just a rip-off of Adobe Flash, and so I wanted Flash to remain dominant.

I finally started learning Flash, and have decided it sucks compared to SilverLight.

Flash is great for creating pre-defined animations, but for programming complex dynamic animations, it has issues.

Worse yet, it's code editor is EXTREMELY hard to use.

And the ActionScript compiler even produces incorrect error messages.

All up, whilst a week ago I had high hopes of adding my own bit of momentum to the Flash technology, I am now inclined to believe that SilverLight will annihilate it, due if nothing else to vastly better development tools for complex programmatically-controlled animations.

So, for example, I wanted to accomplish the simple task of creating a button in Flash that, when clicked, would respond visually so I knew I was correctly handling the mouse click event.

I decided to make my button turn semi-transparent when clicked - just an elementary visual confirmation that my event handler fired.

I drew my button (an arrow) with the crappy drawing tools in Flash. (I see now why the average Flash artist would start in Illustrator, and only go to Flash once all their artwork was finished.)

I converted it to a symbol, and in the library, chose the "Button" type (instead of MovieClip or Graphic).

All should be well, or so I thought. I then proceeded to use the stock-standard ActionScript 3.0 Flash CS4 button event handling code :

function myHandler()
{
myButton.alpha = 0.1;
}
myButton.addEventHandler(MouseEvent.CLICK, myHandler);

Right off the bat, the editor is TERRIBLE. Microsoft has this thing called "Intellisense", that I just took for granted. But seeing that one of their chief rivals, namely Adobe, can't create something even half as good, makes me realise that Microsoft is actually quite good at creating code editors.

Oh - for sure - Flash has an "Intellisense" equivalent, but only if you declare a strongly-typed variable. But why should I have to do that? Flash already knows that "myButton" is a reference to that button on-screen, so why should I have to declare yet another variable just to get strong typing?

Anyhow, I dutifully do so :

var myStronglyTypedButtonReference:? = myButton;
function myHandler()
{
myStronglyTypedButtonReference.alpha = 0.1;
}
myStronglyTypedButtonReference.addEventHandler(MouseEvent.CLICK, myHandler);

Snag. What type to use?

Again, the code editor is crappy to the max.

Fortunately, there is a very-slow-to-use (no search functionality) class list on the left-hand-side of the editor. It is categorised, which means that whilst my intuition tells me I probably need to find a class called "Button", I need to search through package after package after package. Oh - at the very end there is an "Index" option, which I use. On my powerful computer, it still takes too many seconds to prepare the index, but I am finally rewarded. In the index I find a Button class, and it is in the fl.controls package.

var myStronglyTypedButtonReference:fl.controls.Button = myButton;
function myHandler()
{
myStronglyTypedButtonReference.alpha = 0.1;
}
myStronglyTypedButtonReference.addEventHandler(MouseEvent.CLICK, myHandler);

You'd think that would work. But no.

Flash now complains that "Type was not found or was not a compile-time constant: Button". Fat lot of good that is!

I search and search. The answer almost everyone gives is "just add a button to your stage then delete it straight away, and this will add the necessary library code to your project".

Ummm - but don't I already have a button on my stage? I mean, this arrow I drew is very definitely a button.

I add another copy of the arrow button from the Library to the ActionScript layer, just in case that will help, but the problem persists.

Prompted by one web page, I look at my class path, but that has nothing to do with the problem.

Finally, I find a web page that gives me the clue I need. Check out WarpZone's contribution here. Turns out you need to open the "Components" window, and drag a "Button" control from that "Components" window onto your stage.

So I do it.

And now Flash complains that it can't convert a SimpleButton to a Button!!!

Can I just say that this is really really really stupid. In SilverLight, it is quick & easy to determine the data type of any control on the "stage". But in Flash, it seems you have to just guess, then look for compiler error messages or runtime error messages that would indicate if you guessed wrong!

So I need to use "SimpleButton", not "Button".

var myStronglyTypedButtonReference:fl.controls.SimpleButton = myButton;
function myHandler()
{
myStronglyTypedButtonReference.alpha = 0.1;
}
myStronglyTypedButtonReference.addEventHandler(MouseEvent.CLICK, myHandler);

Problem : SimpleButton is not in the fl.controls package. Groan. Back to the Index. Oh - guess what - it's so dumb it hasn't cached the results of the last time I opened the index. So it spends way too much time once more opening the index.

But at least I can find SimpleButton without too much more pain. It lives in flash.display.

var myStronglyTypedButtonReference:flash.display.SimpleButton = myButton;
function myHandler()
{
myStronglyTypedButtonReference.alpha = 0.1;
}
myStronglyTypedButtonReference.addEventHandler(MouseEvent.CLICK, myHandler);

Extremely unintuitive so far! But surely I have arrived, no?

But no.

When I run, Flash tells me :

ArgumentError: Error #1063: Argument count mismatch on Untitled_fla::MainTimeline/myHandler(). Expected 0, got 1.

Wait a moment - expected ZERO, got ONE?

Adobe, do you know how to write compiler error messages?

My function takes ZERO arguments. If ZERO are expected, then things should work fine!

But, suspecting sloppiness on Adobe's part, I figure that they probably intended to say "expected ONE, got ZERO". So more searching on the web, and I find a code example that uses a single argument of type Object for event handlers. I try it, and at last it works :

var myStronglyTypedButtonReference:flash.display.SimpleButton = myButton;
function myHandler(eventObj:Object)
{
myStronglyTypedButtonReference.alpha = 0.1;
}
myStronglyTypedButtonReference.addEventHandler(MouseEvent.CLICK, myHandler);

Once again, were it SilverLight, it would have been much quicker & easier for me to identify which argument(s) are required for the event handler, and what data type each argument needs to be.

Oh - and SilverLight does at least tend to give ACCURATE error messages.

And this is just a small sliver of my Flash woes. It is horribly unintuitive.

Flash, I wanted to support you, to cheer you on in the race against Microsloth, but I am deeply shocked, saddened, and surprised to find that from a programmability perspective, Microsoft has already won the race. You suck.

I hope it doesn't stay this way.

UPDATE : Despite its many faults and failings, Flash can do really powerful things when you finally figure out how to do things. (It's the "finally figure out" process that Adobe has made waaay too hard.) So for example, here are two pages with EXCELLENT introductory information that has helped me immensely in my quest for complex dynamically-generated Flash animations :

Core Display Classes in Adobe Flash

How to use the Adobe Flash Drawing API at runtime