In the example, the click handler would never get called if you clicked the sprite. Technically, it’s not the filter that’s directly contributing to the problem, it’s that the filter automatically sets cacheAsBitmap to true for the sprite. CacheAsBitmap and masks don’t play well together when it comes to mouse interaction. The workaround is to wrap the maskee within another sprite. The outer sprite gets the filter while the inner sprite gets all the children and the mask. You can see an example of this workaround in the DisplayObject Quirks and Tips post. If you’re dealing with many sprites though, this can get really tedious. Wouldn’t it be nice to have a sprite that just did the dirty work for you? I don’t want to deal with manually creating additional sprites, nesting them, tracking which sprites are nested…ugh…makes me cringe.

Here’s CabMaskableSprite. Use it like a regular sprite. It does the dirty work for you.

// Copyright (c) 2010 Aaron Hardy//// Permission is hereby granted, free of charge, to any person// obtaining a copy of this software and associated documentation// files (the "Software"), to deal in the Software without// restriction, including without limitation the rights to use,// copy, modify, merge, publish, distribute, sublicense, and/or sell// copies of the Software, and to permit persons to whom the// Software is furnished to do so, subject to the following// conditions://// The above copyright notice and this permission notice shall be// included in all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR// OTHER DEALINGS IN THE SOFTWARE.

/** * When a display object has cacheAsBitmap set to true and a mask applied to it, a bug appears * in the Flash Player which prevents the display object from dispatching any mouse events. The * workaround is to have an outer display object which has cacheAsBitmap set to true and a * nested display object which has the mask. When we run into this scenario of having both * cacheAsBitmap set to true and a mask, this sprite will create a nested sprite that will * contain the mask and all children. */ public class CabMaskableSprite extends Sprite { /** * The nested sprite that will contain the children and the mask when nesting is needed. */ protected var nestedDisplay:Sprite;

private var _nest:Boolean;

/** * Whether to nest a sprite to support a filter and a mask. */ protected function get nest():Boolean { return _nest; }

/** * Moves children and mask from the nested sprite to the parent (this sprite). */ protected function doUnnest():void { if (!nestedDisplay) { throw new Error('nestedDisplay should exist.'); }

addEventSwallowers();

super.mask = nestedDisplay.mask; nestedDisplay.mask = null;

var i:int = nestedDisplay.numChildren - 1;

while (i > -1) { addChildAt(nestedDisplay.getChildAt(i), 0); i--; }

removeChild(nestedDisplay); nestedDisplay = null;

removeEventSwallowers(); }

/** * Adds listeners for events that will be dispatched while nesting or unnesting. We don't * want these events to be dispatched because the process should be as transparent as * possible. */ protected function addEventSwallowers():void { addEventListener(Event.ADDED, swallowEvent); addEventListener(Event.REMOVED, swallowEvent); addEventListener(Event.REMOVED_FROM_STAGE, swallowEvent); addEventListener(Event.ADDED_TO_STAGE, swallowEvent); }

/** * Whether graphics have been requested at least once. Because graphical drawings can't * be moved to/from the nested sprite, we must always have a nested sprite and use its * graphics once graphics is requested for the first time. */ protected var graphicsRequested:Boolean = false;