The Loader and the Mouse: Why AS3 Is "Too Hard"
The Loader class is able to capture mouse events. It has mouseEnabled, mouseChildren, and can dispatch mouse events. However, it does not have buttonMode or useHandCursor, which are integral parts of mouse interactivity.
Loader extends InteractiveObject, like its sibling Sprite. Here's the definition of InteractiveObject from the AS3 Documentation:
"The InteractiveObject class is the abstract base class for all display objects with which the user can interact, using the mouse and keyboard."
The intention is there. Loader extends InteractiveObject. A Loader can interact with the mouse, including the ability to capture and dispatch mouse events, but it cannot show a finger on roll over, a fundamental interaction with the mouse. Um…okay…
In Defiance Of Logic
This decision has some interesting consequences. They're the exact type of consequences that Colin Moock alludes to in his "AS3 is too hard" post. In this case, AS3 is counter intuitive to common sense, and contradicts its own architecture. The Loader looks like a duck, walks like a duck and talks like a duck, but the Flash player team decided that you shouldn't be able to treat it like a duck.
Sprite is a direct sibling to Loader, and it isn't until Sprite that you get the properties and methods you need to support mouse interaction, properties and methods that are implied by inheriting from InteractiveObject. This does not make sense.
The technical consequence of this decision is that you cannot load a Bitmap using Loader and make it show the finger mouse cursor on rollover until you take it out of the Loader and put it in a Sprite (not a very intuitive API), or wrap the Loader in a Sprite (yay bloat!). Notice that you can make it "interactive" by adding a MouseEvent listener to the Loader, you just can't get expected interactive behavior by doing so.
Similarly, you cannot load a SWF using Loader with the same issue as above, with an important distinction. While a MovieClip is allowed to have mouse interactivity and has buttonMode and useHandCursor (inherited from Sprite), because of security, you cannot do the following:
Loader.content.buttonMode = true; Loader.content.addEventListener(MouseEvent.CLICK, onClick);
Does Flash throw an error when you try to do either of these? Surprisingly, no. No warning, no error. It just fails gracefully, something that so many AS3 evangelists say was one of the biggest flaws of AS2, touting AS3 as the panacea for all our debugging woes. So, if you're a developer, you might think you can do that, but you can't. Where's the AS3 runtime security error to tell me why my code doesn't work?
What We Have Here Is A Failure To Communicate
If you read the various posts for why newbies should learn AS3, error reporting is one of the most popular arguments. The majority of posts I've read in support of AS3, including Colin Moock's article (written six months prior to his "AS3 is too hard" article that explained how "AS3 is not hard", well played, Colin), use logic similar to Microsoft's Mojave Experiment. They show only the most simplified use cases and don't take into account the real, everyday reasons why people have difficulties and challenges.
I'm an expert developer, so I quickly grasp why you can't add a MouseEvent listener to Loader.content (security), but people less experienced (the majority of Adobe's Flash user base) might waste hours (or days) trying to figure out why it isn't working, especially without an error telling them what's wrong.
How would you search for this on the web if you didn't know what was causing this behavior? What keywords would you use? It's not explicitly stated in the documentation. All of this adds up to a bad customer experience.
Faster Player, Slower Workflow
So, with loaded SWFs, you are forced to write code inside the SWF that will bubble mouse events up. You cannot apply mouse events on a loaded SWF that just contains content and no code, like if you're managing a lot of assets with a designer and you don't want them to have to write any code. You know, a typical and common work flow.
(A trivial example: it's a well-known fact that transparent PNGs maintain their transparency but are significantly smaller if you import them into SWFs and use JPEG compression.)
Instead, you need to take the Loader.content out of its InteractiveObject (Loader) and put it into another InteractiveObject (Sprite) so you can make it interactive.
Read that sentence again. Let it sink in. That kind of architecture doesn't even make sense to the experts AS3 was written for.
This is just one example of why AS3 isn't being picked up by agencies who are steadfastly sticking with AVM1.
Give And Ye Shall Receive
If the Flash player team allows Loader to be interactive, honoring its inheritance chain, they will have improved AS3 in measurable ways that go beyond just the API. They will have made Loader logical and intuitive to average Flash developers trying to learn AS3, and made it worth the hassle of writing the extra code AS3 requires. Without it, they've only made their development more difficult and also driven home that AS3 is hard and doesn't make sense and they should just stick with AS1/AS2 because it's safe and it works.
There are many decisions like this that have been made in AS3, decisions that leave a majority of Adobe's Flash user base nonplussed, intimidated, and actively dissuaded from learning it because certain things don't make sense anymore. It's not just that things have changed or gotten more strict, a series of decisions were made in AS3 that simply don't make sense from an end-user perspective. They've made AS3 too hard.
I'm certainly open to hearing arguments why Loader shouldn't have the mouse interaction properties and methods implied by InteractiveObject — useHandCursor, buttonMode, startDrag() and stopDrag() — but I can't think of any reasons. Your API suffers, and it doesn't matter how good you think your architecture is, the end result is your software is difficult to use, and you've basically told your core customer base "L2P". This is what is known in customer relations as a "faux pas".
Fait Accompli
It's interesting to me how a seemingly small detail like not allowing Loader to actually be an InteractiveObject has such a profound and widespread effect. But, in all honesty, AS3 is burdened by many of these decisions which we are now stuck with (backwards compatibility), and, collectively, they have scared off a ton of Flashers. These Flashers feel like they should jump in, like they're missing out, but every time they get in the ocean, shark fins like these start appearing.
Prior to AS3, Flash had a low barrier of entry. AS3 raised it significantly, in more ways than just the amount of code. Philosophical decisions have been made that resulted in the API being confusing and illogical. Even one of AS3's greatest strengths (error reporting) is completely absent in this case and many others, such as SoundChannel.transform.volume = value. You're not allowed to do that (don't get me started), but Flash doesn't throw an error when you do (why not?). This one snags almost everyone learning AS3 (the Sound API as a whole is pretty poor). No amount of explaining is going to change the fact that using the Sound engine is too difficult.
These are common, everyday tasks in Flash, and the APIs for these tasks were not well thought out. As a result, they are confusing to both newcomers and seasoned developers alike. To top it off, errors that should be expected on these common tasks simply don't happen.
The argument that AS3 is better because it gives you errors as feedback when you make mistakes is as misleading as using AS1 code to show how AS3 is easy to learn (many bloggers are guilty of this), or how a short, controlled tour of an operating system on a custom built computer shows how Vista is a fast, easy-to-use piece of software.
A Bright Future For Flash
I'm one of the few experienced Flash developers entrenched in the camp that AS3 is not appropriate for most Flashers to use and they're better off sticking with AS1/AS2 (there are quite a few of us, some quite famous in the community). It's too complicated, too tricky and requires that you have a lot of experience with debugging and generally solid coding practices (especially because AS3 itself doesn't always follow them).
While there's no way to really fix any of this until AS4, I believe they can, and I sincerely hope they let us in on the ground floor so we can help Adobe help us. The good news is that AS3 has given us plenty of room for improvement, it's given us a fantastic view of what's possible, and everyone's learned some valuable lessons along the way.
It's not only possible to make a great API that's easy to use and extremely powerful at the same time, it's what Adobe must do if they want to bring everyone in the Flash community forward together.
Posted in Actionscript, Flash, Rants
September 4th, 2008 at 10:03 am
Articles like this help create
awareness, change, and make it easier for people to discover the problem when they search for solutions to their issues.
I suspect you are familiar with the specific scenario this has raised for me trying to enable the mouse cursor in a loader object in the display list of a current project on which I am working.
To exacerbate the issue, in a multi-swf, layered project, users like myself potentially first have to find out which object(s) are obstructing others before you realize they were obstructing a loader, not a MovieClip. The link you posted on the Gaia forums was helpful with this:
http://labs.bigspaceship.com/2008/08/05/snaring-mouseenabled/
Thanks again for writing about topics like these.
September 4th, 2008 at 10:27 am
In my opinion, it is not logical that a Loader should get mouse interactivity. It is logical for a Loader to load stuff and then to hand it to something else. In that sense I'd remove all mouse interactivity from it.
AS3 might not be perfect, but frankly, what is?
September 4th, 2008 at 10:38 am
@zedia.net: On the other hand, Loader does extend DisplayObjectContainer, which extends InteractiveObject…which does make a logical case for Loader getting mouse interactivity.
September 4th, 2008 at 11:07 am
Ya I think that's where the problem is coming from. It make sense that a Loader should be a DisplayObjectContainer but it doesn't make sense that it should be an InteractiveObject.
To keep it logical, I wouldn't even make the Loader a DisplayObject. That way there would be no confusion at all. You would have no choice to put the Loader.content into a DisplayObject to add it to the stage. The problem is that this would make it even more difficult for neophites.
I guess the Loader is the way it is because it's a compromise between two worlds.
September 4th, 2008 at 11:15 am
Agreed: It makes sense given this the object hierarchy is how it is, it just doesn't necessarily make sense that it is how it is.
September 4th, 2008 at 3:40 pm
Great article, Steven. I didn't know that Loader doesn't let you set useHandCursor. I see no good reason why that should be the case. Though I haven't needed to do it yet in any of the projects I've worked on, I'm a little annoyed now that I can't.
Did you submit this to bugs.adobe.com so that we can vote for it?
September 4th, 2008 at 5:57 pm
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/Sprite.html
Loader is a direct sibling to Sprite in that they share the same parent (DisplayObjectContainer), but while Sprite gets your standard Flash mouse stuff, specifically buttonMode, useHandCursor, startDrag() and stopDrag(), Loader gets none of these measly FOUR things that truly make it worthy of inheriting InteractiveObject.
There's no good reason for this. They should treat Loader the same as Sprite as far as interface goes.
September 15th, 2008 at 4:58 pm
Oh, boohoo, so Adobe used a different class then they should've. That's terrible!
"Made AS3 hard" now that's an interesting statement. You have never coded C/C++ or assembly or any other compilable language, have you?
I bet adobe had a good reason to make flash.display:Loader as a DisplayObject. it's THEIR API and the hypervisor that is running behind your back knows what to do with it.
Have you ever heard of Loader's Event.COMPLETE event? you can actually copy the newly loaded object instead of using the Loader as a warper as intended (you know, addChild(event.target.content);)
Next time you try to blame an API coder, seriously sit down and discuss it with yourself instead of running and immediately ranting about it in your blog.
September 16th, 2008 at 12:12 am
It's obvious you didn't read my article. I didn't say it was a problem that Loader was a DisplayObject. In fact, I didn't mention DisplayObject once. And you accuse me of not taking time to think about what I write first? That's adorable.
I saw your blog. I'm not sure how you can "read" my article and conclude you are the target audience. Since you admitted to being new to Flash on your own blog, you not only have limited knowledge of the majority of the Flash user base, you also have limited experience with Flash in general. This means your opinion on this matter is not as well-informed. Additionally, your response only proves my point. You just told the vast Flash developer base of novice coders "L2P". You live in another world, a world completely separated from the majority of people using Flash, and then you have the audacity to come into their world and call them all amateurs. Dale Carnegie would be proud.
The implication you have made is that their API is the way it is because they architected their code in such a way that it makes sense behind the scenes for it to work the way it does. You all but say I'm too stupid to understand that, even though it's a poor argument to begin with. If they had been more thoughtful in their approach in the first place, we wouldn't be stuck with illogical, overcomplicated APIs, and classes that inherit InteractiveObject but which themselves are not interactive. There's no amount of argument anyone could provide that could adequately explain that kind of flawed architecture. It's their code, as you pointed out, so it's their responsibility as the authors, and has nothing to do with the language itself. Their architecture is illogical, and you say I'm too stupid to get it?
Ad hominem is always a constructive way to debate. Kudos.
September 17th, 2008 at 7:31 am
Great article, as another experienced as3 and as2 programmer I feel it's a shame mentioning the return on time investment in as2 is better than as3 seems to be a bit of a tabboo subject in some flash circles
The idea that newer products must be better than older products in built into so many people
It definately seems as3 is a case of one step forward, two steps backwards, and another to the side,
though lack of reporting is bad (try creating a context menu item with the string "settings" in it, it fails silently), what seems more worrying is adobes lack of respect for backwards compatablity in flash 9,
the security model has been changes something like 3 times this version, each time breaks pre-existing content on the web, having a reliable platform is a real deal breaker for me
Anyway great article
September 17th, 2008 at 9:57 am
http://livedocs.adobe.com/flex/3/langref/flash/ui/ContextMenuItem.html
To be fair, the documentation for ContextMenuItem states that "Settings" is not allowed, but this information was never distributed with Flash until CS3. By contrast, I challenge anyone to find any documentation clearly stating that adding a MouseEvent.CLICK listener to Loader.content is not allowed.
September 17th, 2008 at 3:04 pm
I don't think this is really a big deal. If you think of the Loader as an object that simply loads then passes it's content off there is no problem.
It only becomes strange when you start investigating the underlying class, which I don't think is really going to be affecting beginners.
September 18th, 2008 at 9:15 am
I agree with George K. I've never though of loader as something you would even want to use as an interactive object. It seems fairly obvious/intuitive that the function of the Loader is to freaking load some other content and pass it off to whatever container you want to add it to. I don't understand why this warrants a whole blog rant… although I did enjoy reading the discussion!
p.s. on a side note, I literally cannot fathom why any experienced programmer (not a script kiddie) would think that as2/as1 is "better" than as3.
September 18th, 2008 at 9:48 am
I do think agree that its wierd that it doesn't implement all the necessary interactive features you mention. But I personally LOVE AS3, it gives me all the tools to do exactly what I want to do. Could it be better? Of course. As far as the error reporting, I am constantly getting tons of helpful errors that point directly to the problem area within my code. Surely foreseeing every error is a difficult task, and new errors should be brought to Adobe's attention, not necessarily used to spread disdain for the product. I do understand that you respect Adobe, and are writing from a very "customer" perspective, but we are all on the same team here. Adobe has always been great at involving their customers very much in the development of new products, certainly more than other companies. Regardless of my few disagreements, a great and informative article!
September 18th, 2008 at 11:47 am
"By contrast, I challenge anyone to find any documentation clearly stating that adding a MouseEvent.CLICK listener to Loader.content is not allowed."
It is allowed — it just won't do anything. Moreover, the documentation gives no reason to think it would do anything.
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/Loader.html#content
The Loader.content property is of the type DisplayObject. Let's look up the events dispatched by a DisplayObject.
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/DisplayObject.html#eventSummary
Hmm, no mouse events!
Of course, this is stating it by omission, but you can't expect them to document everything that *doesn't* exist in the language.
September 18th, 2008 at 11:52 am
If you trace(loader.content is MovieClip) after a swf is loaded, it will return true.
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/MovieClip.html#eventSummary
Hey, lookie here! MovieClip has mouse events.
"A" for effort, Beardo!
September 18th, 2008 at 3:37 pm
@george Many beginners have reported these very misunderstandings to me. "Loader can have MouseEvents but cannot have buttonMode?"
@mark This is the core of the problem. Under your proposed usage, Loader should not be a DisplayObject and should not be allowed to be added to the stage. I don't necessarily disagree with that idea.
Instead, they've blurred the lines by giving us partial functionality (being able to add Loader to the stage as a convenience to the alternative of stripping out the content and adding it instead). Why not finish it? Either do it or don't, but they did it halfway and that's why it's confusing.
They are blurring the lines here between strict architecture and ease of use. If they wanted to be strict, they should have created a BitmapLoader and a SWFLoader class, and forced you to use the proper one and strip/apply the content of it into a DisplayObject (Sprite or MovieClip). Instead, they give you a single class and only implement it part of the way.
If you look at the current architecture, you see that they had Loader and its sibling Sprite extend InteractiveObject, but Sprite got the basic interactive stuff for containers and Loader didn't. Loader is like the kid on Christmas morning wondering why his stepmother didn't give him as nice a gift as his stepbrother.
So the question I have is why didn't they just have Loader extend Sprite instead of being its weird sibling? Or, why didn't they just take the Loader all the way and make it literally just a loader that you MUST strip the content out of and add that to the stage? They took it halfway and thus provided confusion for not only beginners but experts, too.
I didn't say I think that AS1/AS2 is better than AS3. I'll never use AS2 again. I meant that it's better (i.e. more appropriate) for script kiddies, designers and non-coders in general.
September 27th, 2008 at 6:01 pm
It has to do with the Display Tree. Loader is a temporary mechanism to dealing with assets that have not been added to the main display tree directly.
The reason AS3 and AVM2 are fast is this new way to handle children in the tree. The problem is when you need to add to that dynamically you need an object to do so that it can be recognized but not fully added until it is ready. Thus the Loader. Just add the loader content to the main tree by appending it to something there and you are good.
September 27th, 2008 at 6:05 pm
Another way of putting it is Loader is a wrapper that contains an object in Utero to the real display tree.
October 2nd, 2008 at 10:37 pm
I strongly agree with this article. There are so many non-intuitive problems with AS3 that make development for an "intuitive mind" unnecessarily difficult. It could be more the fault of a deficient Flash IDE than anything else, though. For instance, removing on/onClipEvent is understandable, but it hasn't been replaced with anything useful. Navigating the timeline at runtime can wreak havoc on your DisplayObject references and events. Error messages and documentation are very cryptic. IDE linkage between .as files and .fla contents is almost non-existent (for instance, why can't you click on an instance and see if it has a Class associated with it, and go directly to the class file, or even show the class script directly in the Actions panel?)
And am I the only only for whom Flash CS3 crashes constantly? No other version of Flash I've owned did this (I skipped MX2004, though.) it certainly aggravates the already slow and cumbersome AS3 development process.
Sigh. I miss the days when Flash was exciting, fun, and easy to explore.
October 18th, 2008 at 12:12 am
Very nice article. I started now with AS3 because I need to load external Papervision3D QTVR's into a project and is getting quite confused of all issues migrating from AS2.
What absolutely do not make sense is that its impossible to unload(). How could they missed a thing like that and still not fixed it?
AS3 is no fun as all, I just wish it was.
October 30th, 2008 at 9:57 pm
boo hoo! loader doesn't have hand cursor! get over it. Sure, as3 is not perfect but even not having to delegate makes it worthwhile without going on about the display list or event handling or anything else that makes it so good.
Loader is for loading. Wow, you can by some freak of inheritance add mouse events to a loader. cool. use that if you don't care about hand cursors (which I rarely bother with for buttons even) or put it in a sprite.
Complaining that you have to put a loader in a sprite adds bloat is surely forgetting about sprite at all, let alone shape or displayobject and even loader.
Finally gone are the days when anything you needed interactive had to be a movieclip. (getChildAt() - sweet)
Learn as3. Even with all the hardship and extra coding, it just makes sense.
October 30th, 2008 at 10:03 pm
Forgot to mention xml e4x! So good. So many benefits. Picking on a hand cursor seems amateur.
October 30th, 2008 at 10:06 pm
And Event bubbling! mouseEvent target, currentTarget, ROLL_OVER, MOUSE_OVER. It just goes on…
October 31st, 2008 at 2:42 am
You can use a loader to load content and then draw it out into a different sprite, such as caching images into an array (a programmatic library of images) and then drawing them out at a later stage. I've done that, it makes sense to me, you don't have to make the loader object interactive - perhaps it wasn't intended that way.
But I do agree that some things are vastly more complicated. The hidden method setTimeout - very useful, a one line call … is advised not to be used in favour of the Timer class … an object that requires creating, methods attaching, and starting. Four lines of code where one simple line of code worked before. It may be more 'object orientated' but this isn't necessarily a good thing.
Your article made me think about that.
October 31st, 2008 at 12:44 pm
The inconsistency in logic is undeniable, untenable, and unacceptable. If 'Loader is for loading', then why does it subclass DisplayObject? The gravity of this issue is subjective but its existence is objective. Why bother going OO if you're not going to go all the way- with all concerns separated- with all logic sound? Why merge a loader and a display object? Why have an InteractiveObject that can't have a hand cursor? While I believe AS3 is significantly better than AS2, Steven has a point in that it's not without issues. I think the wrinkles are fewer which makes them, arguably, more prominent, annoying, and difficult to understand.
November 10th, 2008 at 11:52 pm
I also agree that being sibling of Sprite and therefore inheriting interactive functionality is misleading. The biggest mistake is just not explaining it in the manual. A question I am asking myself is: What shall they do now? Remove Loader from InteractiveObject? That would break applications more seriously then security concerns because people build on that API. So there next step should be to better communicate the use of the loader class.
I really guess that when they were planing the hierarchy someone came up with the idea to make Loader both a loader class and displayobject container to let people easily load and display pictures (without interactivity). And when we look at the hierachy we see that DisplayObjectContainer is child of InteractiveObject… so no way around that. It was definitely a tradeoff and at the end a misleading communication. But good to have a blog like this
There must be something that differenciates the pros from the beginners.
November 14th, 2008 at 9:06 am
Great article!
I hope the chuckleheads at Adobe who designed AS3 have read this. I have struggled mightily with some of the same issues. I spent (wasted?) a lot of time becoming proficient in AS2, only to have the rug pulled out from under me with the release of AS3.
AS2 was certainly not perfect, and yes, there were some things from a coding perspective that might not have been "right", but AS2 was inituitive and worked much better for what Flash is, an animation IDE. I'm not sure why Adobe decided that if you want to learn Flash, you now must be a Java developer.