The power and genius of mouseChildren and mouseEnabled.

Jan 20

I admit, this post will be useless for most readers of this blog. But if you happen to be an Actionscript programmer… I had a minor epiphany today from which you might benefit.

Since I started writing AS3 code, I’ve generally viewed the mouseChildren and mouseEnabled properties of the InteractiveObject class (and by extension the Sprite class) as relatively superfluous. They existed as little more than a recourse for when something accidentally got ‘in between’ the mouse and a button that needed to be pressed. And in a sense that is true. But I realized today that those crafty AS3 creators had bestowed upon me a much more substantial tool than I’d first realized.

Fundamentally, these two properties are straightforward. Setting a Sprite’s mouseEnabled property to false tells that Sprite to not bother interacting with the mouse. In other words, to stop dispatching MouseEvents such as MouseEvent.CLICK. Likewise, setting a Sprite’s mouseChildren property to false tells the children of that Sprite to stop dispatching MouseEvents. By default, both properties are set to true.

The magic comes by virtue of the fact that these two properties work independently of each other. If a Sprite has children, setting that Sprite’s mouseEnabled to false does not prevent the Sprite’s children from dispatching MouseEvents. Similarly, setting the Sprite’s mouseChildren to false doesn’t prevent the sprite itself from dispatching MouseEvents. Why is this cool? Let me count the reasons:

  • Sprite ‘flattening’. It used to drive me nuts that that a button made of multiple sub-elements (label, hilight, border, icon, etc) would have an indeterminate MouseEvent ‘originator’. That is, the target property of the MouseEvent would be ‘label’ or ‘highlight’ or whatever depending on the exact pixel over which the mouse rested, rather than simply ‘myButton’. I found myself putting invisible ‘mousetrap’ layers in my buttons to sit on top of everything to fix this. It turns out I don’t need to. By setting myButton.mouseChildren = false all the button parts become a single unit, collectively dispatching MouseEvents with a target of ‘myButton’.
  • Group disabling. Need to disable a whole group of buttons? Make them siblings and set the parent Sprite’s mouseChildren to false.
  • Event-bubbling simplification. By setting a container Sprite’s mouseEnabled = false but leaving mouseChildren = true, you prevent the ‘middleman’ from sending unnecessary MouseEvents to high-level MouseEvent handlers. Imagine a calculator, with multiple keys, a display screen, a surrounding ‘case’, a nice little Texas Instruments logo, whatever. If I add a MouseEvent.CLICK listener to the high-level calculator object, I will receive all of the various key clicks, but I will also receive events from the other child elements… the display, the case, the logo. Even if I set those elements to mouseEnabled = false, the calculator Sprite itself will still trigger its own MouseEvents when I roll over them. By following up with calculator.mouseEnabled = false, the high-level listener will now only receive events from the children that matter, and will not be encumbered with ‘false positives’.

Given this greater understanding, I almost wonder why the AS3 creators chose to set the default of mouseEnabled to true. After all… aren’t there generally far more ‘passive’ display objects on the stage than interactive ones? I’m sure they had a reason, and it’s probably one that I could find by Googling around a bit… but enough is enough. Hardcore geek session over.