All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scaffold.libs_as.starling.display.DisplayObjectContainer.as Maven / Gradle / Ivy

// =================================================================================================
//
//	Starling Framework
//	Copyright 2011-2015 Gamua. All Rights Reserved.
//
//	This program is free software. You can redistribute and/or modify it
//	in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================

package starling.display
{
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.system.Capabilities;
    import flash.utils.getQualifiedClassName;

    import starling.core.starling_internal;
    import starling.errors.AbstractClassError;
    import starling.events.Event;
    import starling.filters.FragmentFilter;
    import starling.rendering.BatchToken;
    import starling.rendering.Painter;
    import starling.utils.MatrixUtil;

    use namespace starling_internal;
    
    /**
     *  A DisplayObjectContainer represents a collection of display objects.
     *  It is the base class of all display objects that act as a container for other objects. By 
     *  maintaining an ordered list of children, it defines the back-to-front positioning of the 
     *  children within the display tree.
     *  
     *  

A container does not a have size in itself. The width and height properties represent the * extents of its children. Changing those properties will scale all children accordingly.

* *

As this is an abstract class, you can't instantiate it directly, but have to * use a subclass instead. The most lightweight container class is "Sprite".

* * Adding and removing children * *

The class defines methods that allow you to add or remove children. When you add a child, * it will be added at the frontmost position, possibly occluding a child that was added * before. You can access the children via an index. The first child will have index 0, the * second child index 1, etc.

* * Adding and removing objects from a container triggers non-bubbling events. * *
    *
  • Event.ADDED: the object was added to a parent.
  • *
  • Event.ADDED_TO_STAGE: the object was added to a parent that is * connected to the stage, thus becoming visible now.
  • *
  • Event.REMOVED: the object was removed from a parent.
  • *
  • Event.REMOVED_FROM_STAGE: the object was removed from a parent that * is connected to the stage, thus becoming invisible now.
  • *
* * Especially the ADDED_TO_STAGE event is very helpful, as it allows you to * automatically execute some logic (e.g. start an animation) when an object is rendered the * first time. * * @see Sprite * @see DisplayObject */ public class DisplayObjectContainer extends DisplayObject { // members private var _children:Vector.; private var _touchGroup:Boolean; // helper objects private static var sHelperMatrix:Matrix = new Matrix(); private static var sHelperPoint:Point = new Point(); private static var sBroadcastListeners:Vector. = new []; private static var sSortBuffer:Vector. = new []; private static var sCacheToken:BatchToken = new BatchToken(); // construction /** @private */ public function DisplayObjectContainer() { if (Capabilities.isDebugger && getQualifiedClassName(this) == "starling.display::DisplayObjectContainer") { throw new AbstractClassError(); } _children = new []; } /** Disposes the resources of all children. */ public override function dispose():void { for (var i:int=_children.length-1; i>=0; --i) _children[i].dispose(); super.dispose(); } // child management /** Adds a child to the container. It will be at the frontmost position. */ public function addChild(child:DisplayObject):DisplayObject { return addChildAt(child, _children.length); } /** Adds a child to the container at a certain index. */ public function addChildAt(child:DisplayObject, index:int):DisplayObject { var numChildren:int = _children.length; if (index >= 0 && index <= numChildren) { setRequiresRedraw(); if (child.parent == this) { setChildIndex(child, index); // avoids dispatching events } else { _children.insertAt(index, child); child.removeFromParent(); child.setParent(this); child.dispatchEventWith(Event.ADDED, true); if (stage) { var container:DisplayObjectContainer = child as DisplayObjectContainer; if (container) container.broadcastEventWith(Event.ADDED_TO_STAGE); else child.dispatchEventWith(Event.ADDED_TO_STAGE); } } return child; } else { throw new RangeError("Invalid child index"); } } /** Removes a child from the container. If the object is not a child, nothing happens. * If requested, the child will be disposed right away. */ public function removeChild(child:DisplayObject, dispose:Boolean=false):DisplayObject { var childIndex:int = getChildIndex(child); if (childIndex != -1) removeChildAt(childIndex, dispose); return child; } /** Removes a child at a certain index. The index positions of any display objects above * the child are decreased by 1. If requested, the child will be disposed right away. */ public function removeChildAt(index:int, dispose:Boolean=false):DisplayObject { if (index >= 0 && index < _children.length) { setRequiresRedraw(); var child:DisplayObject = _children[index]; child.dispatchEventWith(Event.REMOVED, true); if (stage) { var container:DisplayObjectContainer = child as DisplayObjectContainer; if (container) container.broadcastEventWith(Event.REMOVED_FROM_STAGE); else child.dispatchEventWith(Event.REMOVED_FROM_STAGE); } child.setParent(null); index = _children.indexOf(child); // index might have changed by event handler if (index >= 0) _children.removeAt(index); if (dispose) child.dispose(); return child; } else { throw new RangeError("Invalid child index"); } } /** Removes a range of children from the container (endIndex included). * If no arguments are given, all children will be removed. */ public function removeChildren(beginIndex:int=0, endIndex:int=-1, dispose:Boolean=false):void { if (endIndex < 0 || endIndex >= numChildren) endIndex = numChildren - 1; for (var i:int=beginIndex; i<=endIndex; ++i) removeChildAt(beginIndex, dispose); } /** Returns a child object at a certain index. If you pass a negative index, * '-1' will return the last child, '-2' the second to last child, etc. */ public function getChildAt(index:int):DisplayObject { var numChildren:int = _children.length; if (index < 0) index = numChildren + index; if (index >= 0 && index < numChildren) return _children[index]; else throw new RangeError("Invalid child index"); } /** Returns a child object with a certain name (non-recursively). */ public function getChildByName(name:String):DisplayObject { var numChildren:int = _children.length; for (var i:int=0; i out.x) minX = out.x; if (maxX < out.right) maxX = out.right; if (minY > out.y) minY = out.y; if (maxY < out.bottom) maxY = out.bottom; } out.setTo(minX, minY, maxX - minX, maxY - minY); } return out; } /** @inheritDoc */ public override function hitTest(localPoint:Point):DisplayObject { if (!visible || !touchable || !hitTestMask(localPoint)) return null; var target:DisplayObject = null; var localX:Number = localPoint.x; var localY:Number = localPoint.y; var numChildren:int = _children.length; for (var i:int = numChildren - 1; i >= 0; --i) // front to back! { var child:DisplayObject = _children[i]; if (child.isMask) continue; sHelperMatrix.copyFrom(child.transformationMatrix); sHelperMatrix.invert(); MatrixUtil.transformCoords(sHelperMatrix, localX, localY, sHelperPoint); target = child.hitTest(sHelperPoint); if (target) return _touchGroup ? this : target; } return null; } /** @inheritDoc */ public override function render(painter:Painter):void { var numChildren:int = _children.length; var frameID:uint = painter.frameID; var selfOrParentChanged:Boolean = _lastParentOrSelfChangeFrameID == frameID; for (var i:int=0; i, compareFunc:Function, startIndex:int, length:int, buffer:Vector.):void { // This is a port of the C++ merge sort algorithm shown here: // http://www.cprogramming.com/tutorial/computersciencetheory/mergesort.html if (length > 1) { var i:int; var endIndex:int = startIndex + length; var halfLength:int = length / 2; var l:int = startIndex; // current position in the left subvector var r:int = startIndex + halfLength; // current position in the right subvector // sort each subvector mergeSort(input, compareFunc, startIndex, halfLength, buffer); mergeSort(input, compareFunc, startIndex + halfLength, length - halfLength, buffer); // merge the vectors, using the buffer vector for temporary storage for (i = 0; i < length; i++) { // Check to see if any elements remain in the left vector; // if so, we check if there are any elements left in the right vector; // if so, we compare them. Otherwise, we know that the merge must // take the element from the left vector. */ if (l < startIndex + halfLength && (r == endIndex || compareFunc(input[l], input[r]) <= 0)) { buffer[i] = input[l]; l++; } else { buffer[i] = input[r]; r++; } } // copy the sorted subvector back to the input for(i = startIndex; i < endIndex; i++) input[i] = buffer[int(i - startIndex)]; } } /** @private */ internal function getChildEventListeners(object:DisplayObject, eventType:String, listeners:Vector.):void { var container:DisplayObjectContainer = object as DisplayObjectContainer; if (object.hasEventListener(eventType)) listeners[listeners.length] = object; // avoiding 'push' if (container) { var children:Vector. = container._children; var numChildren:int = children.length; for (var i:int=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy