August 5th, 2008
A lot of what we do here at the Spaceship involves complex SWFs loaded in and layered on top of other SWFs. We wind up with a lot of buttons nested underneath of movieclips nested inside of SWFs.
When we got to handling mouse interaction in AS2, this was fine so long as a button wasn’t layered on top of another button. But in AS3 it’s a different ball of wax — each DisplayObject has a mouseEnabled property, which is set to true by default. mouseEnabled means that the DisplayObject in question *can* react to mouse events.
This can be lead to some tricky and irritating issues. Hit the jump for specifically what is happening and how to fix it.
The rule of thumb is more or less this:
When a mouse event happens, the DisplayObject underneath the mouse at the highest depth with mouseEnabled set to true will fire a MouseEvent, which will relay to it’s parent, and it will go all the way down to the stage.
Consider this: MovieClip A is on the topmost layer. MovieClip B has a MouseEvent.CLICK listener. MovieClip A overlaps MovieClip B.
Any time a user clicks on MovieClip A it will hear the MouseEvent and sending it down the chain… MovieClip B would never hear it. This effectively creates the “I’m listening for the mouse but nothing happens for no reason” bug. By setting MovieClip A to mouseEnabled=false, all is well. Note that if MovieClip A had anything nested inside of it, they too would have to be disabled. You can do this either with mouseEnabled=false on each of them painstakingly or by setting MovieClip A’s mouseChildren=false.
So okay! We know what the problem is… a MovieClip can block the mouse from another movieclip. But most of what we’re building in Flash is far more complex than one MovieClip on top of another… is there an easy way to find the culprit of mouse blocking? Indeed there is! Sort of. Just drop this code on your main timeline (or your root class, if you prefer):
var p:* = $e.target;
trace(">>", p.name,": ",p);
p = p.parent;
What we’re doing in the above is listening to the stage for any mouse interaction and then outputting the path on the DisplayList from the origin of the event all the way down to the stage.
We use this as a utility to help us figure out what DisplayObject is blocking our way to the DisplayObjects we actually care to listen to.