/** * Used as a containing clip for many children display objects that need to be sorted visually based on a certain property. * * Author: * Nate Chatellier, e-mail: natejc@natejc.com * * @see http://blog.natejc.com * * Released under the MIT License: * Copyright (c) 2010 Nate Chatellier * 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. */ package com.natejc.display { import flash.display.DisplayObject; import flash.display.Sprite; import flash.events.Event; /** * Used as a containing clip for many children display objects that need to be sorted visually based on a certain property. * * @author Nate Chatellier */ public class SpriteAutoSorter extends Sprite { /** The property of the display object that should be used to sort on. */ public var sPropertyToSortOn :String = "y"; /** Stores a reference to all child display objects contained by this clip. */ protected var _aChildren :Array = []; /** References how many children are thought to be contained by this display object. This is used for protection of something not being accurate and for speed. */ protected var _nNumChildren :int = 0; /* ---------------------------------------------------------------------------------------- */ public function SpriteAutoSorter() { super(); } /* ---------------------------------------------------------------------------------------- */ /** * Makes this Sprite begin sorting every frame. */ public function beginSorting():void { this.addEventListener(Event.ENTER_FRAME, update); } /* ---------------------------------------------------------------------------------------- */ /** * Stop this Sprite from sorting every frame (saves on cpu usage). */ public function stopSorting():void { this.removeEventListener(Event.ENTER_FRAME, update); } /* ---------------------------------------------------------------------------------------- */ /** * Makes sure all display objects contained within this clip are sorted. * * @param $e The dispatched Event.ENTER_FRAME event. */ protected function update($e:Event = null):void { if (_nNumChildren != this.numChildren) this.rebuildChildArray(); this.sort(); } /* ---------------------------------------------------------------------------------------- */ /** * @private * Sorts all display objects contained within this clip based on the attribute specified by sPropertyToSortOn. */ protected function sort():void { _aChildren.sortOn(sPropertyToSortOn, Array.NUMERIC); for (var i:int = 0; i < _nNumChildren; i++) this.setChildIndex(_aChildren[i], i); } /* ---------------------------------------------------------------------------------------- */ /** * @private * Ensures the array that is used to sort the display objects is accurate. */ protected function rebuildChildArray():void { _aChildren = []; for (var i:int = 0; i < this.numChildren; i++) _aChildren.push(this.getChildAt(i)); _nNumChildren = this.numChildren; } /* ---------------------------------------------------------------------------------------- */ /** * Adds a child DisplayObject instance to this clip. The child is automatically sorted based on sPropertyToSortOn. * * @param $mcChild The DisplayObject instance to add as a child of this DisplayObjectContainer instance. * @return The DisplayObject instance that you pass in the child parameter or null if it was already a child of this clip. */ override public function addChild($mcChild:DisplayObject):DisplayObject { if (_aChildren.indexOf($mcChild) < 0) // ensure the object isn't already in the array { super.addChild($mcChild); _aChildren.push($mcChild); _nNumChildren++; this.sort(); return $mcChild; } return null; } /* ---------------------------------------------------------------------------------------- */ /** * Removes the specified DisplayObject instance from this clip.. * * @param $mcChild The DisplayObject instance that is to be removed. * @return The DisplayObject instance that you pass in the child parameter or null if it was not a child of this clip. */ override public function removeChild($mcChild:DisplayObject):DisplayObject { var nIndexOfChild:int = _aChildren.indexOf($mcChild); if (nIndexOfChild < 0) // return null if $mcChild is not a child of this clip return null; super.removeChild($mcChild); _aChildren.splice(nIndexOfChild, 1); _nNumChildren--; this.sort(); return $mcChild; } /* ---------------------------------------------------------------------------------------- */ } }