package aerys.minko.type.loader
{
	import aerys.minko.render.geometry.Geometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.render.resource.texture.TextureResource;
	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.type.Signal;

	public final class AssetsLibrary
	{
		private var _numGeometries 	: uint 						= 0;
		private var _numMaterials	: uint 						= 0;
		private var _numTextures	: uint 						= 0;
		private var _numSymbols		: uint 						= 0;

		private var _geometryList	: Vector.<Geometry> 		= new Vector.<Geometry>();
		private var _materialList	: Vector.<Material> 		= new Vector.<Material>();
		private var _textureList	: Vector.<TextureResource> 	= new Vector.<TextureResource>();
		private var _symbolList		: Vector.<ISceneNode>		= new Vector.<ISceneNode>();

		private var _geometries		: Object;
		private var _symbols		: Object;
		private var _textures		: Object;
		private var _materials		: Object;
		private var _layers			: Vector.<String>;
		private var _nameToLayer	: Object;

		private var _geometryAdded	: Signal;
		private var _symbolAdded	: Signal;
		private var _textureAdded	: Signal;
		private var _materialAdded	: Signal;
		private var _layerAdded		: Signal;

		public function AssetsLibrary()
		{
			initialize();
			initializeSignals();
		}

		public function get numSymbols() : uint
		{
			return _numSymbols;
		}

		public function get numTextures() : uint
		{
			return _numTextures;
		}

		public function get numGeometries() : uint
		{
			return _numGeometries;
		}

		public function get numMaterials() : uint
		{
			return _numMaterials;
		}

		public function getSymbolAt(index : uint) : ISceneNode
		{
			return _symbolList[index];
		}

		public function getMaterialAt(index : uint): Material
		{
			return _materialList[index];
		}

		public function getGeometryAt(index : uint): Geometry
		{
			return _geometryList[index];
		}

		public function getTextureAt(index : uint): TextureResource
		{
			return _textureList[index];
		}

		public function getSymbolByName(name : String) : ISceneNode
		{
			return _symbols[name];
		}

		public function getMaterialByName(name : String) : Material
		{
			return _materials[name];
		}

		public function getTextureByName(name : String) : TextureResource
		{
			return _textures[name];
		}

		public function getGeometryByName(name : String) : Geometry
		{
			return _geometries[name];
		}

		private function initialize() : void
		{
			_geometries		= {};
			_textures		= {};
			_materials		= {};
			_symbols		= {};

			_layers			= new Vector.<String>(32, true);
			_layers[0]		= 'Default';
			for (var i : uint = 1; i < _layers.length; ++i)
				_layers[i]	= 'Layer_' + i;

			_nameToLayer	= {};
		}

		private function initializeSignals() : void
		{
			_geometryAdded	= new Signal('AssetsLibrary.geometryAdded');
			_textureAdded	= new Signal('AssetsLibrary.textureAdded');
			_materialAdded	= new Signal('AssetsLibrary.materialAdded');
			_layerAdded		= new Signal('AssetsLibrary.layerAdded');
			_symbolAdded	= new Signal('AssetsLibrary.symbolAdded');
		}

		public function get layerAdded() : Signal
		{
			return _layerAdded;
		}

		public function get materialAdded() : Signal
		{
			return _materialAdded;
		}

		public function get textureAdded() : Signal
		{
			return _textureAdded;
		}

		public function get geometryAdded() : Signal
		{
			return _geometryAdded;
		}

		public function get symbolAdded() : Signal
		{
			return _symbolAdded;
		}

		public function setSymbol(name : String, node : ISceneNode) : void
		{
			if (_symbolList.indexOf(node) == -1)
			{
				++_numSymbols;
				_symbolList.push(node);
				_symbols[name] = node;
				_symbolAdded.execute(this, name, node);
			}
		}

		public function setGeometry(name : String, geometry : Geometry) : void
		{
			if (_geometryList.indexOf(geometry) == -1)
			{
				++_numGeometries;
				_geometryList.push(geometry);
				_geometries[name] = geometry;
				_geometryAdded.execute(this, name, geometry);
			}
		}

		public function setTexture(name : String, texture : TextureResource) : void
		{
			if (_textureList.indexOf(texture) == -1)
			{
				++_numTextures;
				_textureList.push(texture);
				_textures[name] = texture;
				_textureAdded.execute(this, name, texture);
			}
		}

		public function setMaterial(name : String, material : Material) : void
		{
			material ||= new BasicMaterial();
			name ||= material.name;

			if (_materialList.indexOf(material) == -1)
			{
				++_numMaterials;
				_materialList.push(material);
				_materials[name] = material;
				_materialAdded.execute(this, name, material);
			}
		}

		public function setLayer(name : String, layer : uint) : void
		{
			name ||= 'Layer_' + layer;
			_layers[layer] = name;
			_layerAdded.execute(this, name, layer);
		}

		public function getLayerTag(name : String, ... params) : uint
		{
			var tag	: uint	= 0;

			if (_nameToLayer[name])
			{
				tag |= 1 << _nameToLayer[name];
			}

			for each (name in params)
			{
				if (_nameToLayer[name])
				{
					tag |= 1 << _nameToLayer[name];
				}
			}

			return tag;
		}

		public function getLayerName(tag : uint) : String
		{
			var names	: Vector.<String>	= new <String>[];
			var name	: String 			= null;
			var i		: uint				= 0;

			for (i = 0; i < 32; ++i)
			{
				if (tag & (1 << i))
					names.push(_layers[i]);
			}
			name = names.join('|');

			return name;
		}

		public function merge(other : AssetsLibrary) : AssetsLibrary
		{
			var name	: String	= null;
			var i		: uint		= 0;

			for (name in other._geometries)
				setGeometry(name, other._geometries[name]);
			for (name in other._materials)
				setMaterial(name, other._materials[name]);
			for (name in other._textures)
				setTexture(name, other._textures[name]);
			for each (name in other._layers)
				setLayer(name, i++);

			return this;
		}
	}
}

package aerys.minko.type.loader
{
	import aerys.minko.render.geometry.Geometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.render.resource.texture.TextureResource;
	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.type.Signal;

	public final class AssetsLibrary
	{
		private var _numGeometries 	: uint 						= 0;
		private var _numMaterials	: uint 						= 0;
		private var _numTextures	: uint 						= 0;
		private var _numSymbols		: uint 						= 0;
		private var _numLayers		: uint 						= 0;

		private var _layerList 		: Vector.<String>			= new Vector.<String>();
		private var _geometryList	: Vector.<Geometry> 		= new Vector.<Geometry>();
		private var _materialList	: Vector.<Material> 		= new Vector.<Material>();
		private var _textureList	: Vector.<TextureResource> 	= new Vector.<TextureResource>();
		private var _symbolList		: Vector.<ISceneNode>		= new Vector.<ISceneNode>();

		private var _geometries		: Object;
		private var _symbols		: Object;
		private var _textures		: Object;
		private var _materials		: Object;
		private var _layers			: Vector.<String>;
		private var _nameToLayer	: Object;

		private var _geometryAdded	: Signal;
		private var _symbolAdded	: Signal;
		private var _textureAdded	: Signal;
		private var _materialAdded	: Signal;
		private var _layerAdded		: Signal;

		public function AssetsLibrary()
		{
			initialize();
			initializeSignals();
		}

		public function get numLayers() : uint
		{
			return _numLayers;
		}

		public function get numSymbols() : uint
		{
			return _numSymbols;
		}

		public function get numTextures() : uint
		{
			return _numTextures;
		}

		public function get numGeometries() : uint
		{
			return _numGeometries;
		}

		public function get numMaterials() : uint
		{
			return _numMaterials;
		}

		public function getSymbolAt(index : uint) : ISceneNode
		{
			return _symbolList[index];
		}

		public function getMaterialAt(index : uint): Material
		{
			return _materialList[index];
		}

		public function getGeometryAt(index : uint): Geometry
		{
			return _geometryList[index];
		}

		public function getTextureAt(index : uint): TextureResource
		{
			return _textureList[index];
		}

		public function getSymbolByName(name : String) : ISceneNode
		{
			return _symbols[name];
		}

		public function getMaterialByName(name : String) : Material
		{
			return _materials[name];
		}

		public function getTextureByName(name : String) : TextureResource
		{
			return _textures[name];
		}

		public function getGeometryByName(name : String) : Geometry
		{
			return _geometries[name];
		}

		private function initialize() : void
		{
			_geometries		= {};
			_textures		= {};
			_materials		= {};
			_symbols		= {};

			_layers			= new Vector.<String>(32, true);
			_layers[0]		= 'Default';
			for (var i : uint = 1; i < _layers.length; ++i)
				_layers[i]	= 'Layer_' + i;

			_nameToLayer	= {};
		}

		private function initializeSignals() : void
		{
			_geometryAdded	= new Signal('AssetsLibrary.geometryAdded');
			_textureAdded	= new Signal('AssetsLibrary.textureAdded');
			_materialAdded	= new Signal('AssetsLibrary.materialAdded');
			_layerAdded		= new Signal('AssetsLibrary.layerAdded');
			_symbolAdded	= new Signal('AssetsLibrary.symbolAdded');
		}

		public function get layerAdded() : Signal
		{
			return _layerAdded;
		}

		public function get materialAdded() : Signal
		{
			return _materialAdded;
		}

		public function get textureAdded() : Signal
		{
			return _textureAdded;
		}

		public function get geometryAdded() : Signal
		{
			return _geometryAdded;
		}

		public function get symbolAdded() : Signal
		{
			return _symbolAdded;
		}

		public function setSymbol(name : String, node : ISceneNode) : void
		{
			if (_symbolList.indexOf(node) == -1)
			{
				++_numSymbols;
				_symbolList.push(node);
				_symbols[name] = node;
				_symbolAdded.execute(this, name, node);
			}
		}

		public function setGeometry(name : String, geometry : Geometry) : void
		{
			if (_geometryList.indexOf(geometry) == -1)
			{
				++_numGeometries;
				_geometryList.push(geometry);
				_geometries[name] = geometry;
				_geometryAdded.execute(this, name, geometry);
			}
		}

		public function setTexture(name : String, texture : TextureResource) : void
		{
			if (_textureList.indexOf(texture) == -1)
			{
				++_numTextures;
				_textureList.push(texture);
				_textures[name] = texture;
				_textureAdded.execute(this, name, texture);
			}
		}

		public function setMaterial(name : String, material : Material) : void
		{
			material ||= new BasicMaterial();
			name ||= material.name;

			if (_materialList.indexOf(material) == -1)
			{
				++_numMaterials;
				_materialList.push(material);
				_materials[name] = material;
				_materialAdded.execute(this, name, material);
			}
		}

		public function setLayer(name : String, layer : uint) : void
		{
			name ||= 'Layer_' + layer;
			_layers[layer] = name;
			_layerAdded.execute(this, name, layer);
		}

		public function getLayerTag(name : String, ... params) : uint
		{
			var tag	: uint	= 0;

			if (_nameToLayer[name])
			{
				tag |= 1 << _nameToLayer[name];
			}

			for each (name in params)
			{
				if (_nameToLayer[name])
				{
					tag |= 1 << _nameToLayer[name];
				}
			}

			return tag;
		}

		public function getLayerName(tag : uint) : String
		{
			var names	: Vector.<String>	= new <String>[];
			var name	: String 			= null;
			var i		: uint				= 0;

			for (i = 0; i < 32; ++i)
			{
				if (tag & (1 << i))
					names.push(_layers[i]);
			}
			name = names.join('|');

			return name;
		}

		public function merge(other : AssetsLibrary) : AssetsLibrary
		{
			var name	: String	= null;
			var i		: uint		= 0;

			for (name in other._geometries)
				setGeometry(name, other._geometries[name]);
			for (name in other._materials)
				setMaterial(name, other._materials[name]);
			for (name in other._textures)
				setTexture(name, other._textures[name]);
			for each (name in other._layers)
				setLayer(name, i++);

			return this;
		}
	}
}

Add datastructure to store layers

Add datastructure to store layers


/*

as3isolib - An open-source ActionScript 3.0 Isometric Library developed to assist
in creating isometrically projected content (such as games and graphics)
targeted for the Flash player platform

http://code.google.com/p/as3isolib/

Copyright (c) 2006 - 2008 J.W.Opitz, All Rights Reserved.

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 as3isolib.display.scene
{

	import as3isolib.bounds.IBounds;
	import as3isolib.bounds.SceneBounds;
	import as3isolib.core.IIsoDisplayObject;
	import as3isolib.core.IsoContainer;
	import as3isolib.core.as3isolib_internal;
	import as3isolib.data.INode;
	import as3isolib.display.renderers.DefaultSceneLayoutRenderer;
	import as3isolib.display.renderers.ISceneLayoutRenderer;
	import as3isolib.display.renderers.ISceneRenderer;
	import as3isolib.events.IsoEvent;

	import flash.display.DisplayObjectContainer;

	import mx.core.ClassFactory;
	import mx.core.IFactory;

	use namespace as3isolib_internal;

	/**
	 * IsoScene is a base class for grouping and rendering IIsoDisplayObject children according to their isometric position-based depth.
	 */
	public class IsoScene extends IsoContainer implements IIsoScene
	{
		///////////////////////////////////////////////////////////////////////////////
		//	BOUNDS
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * @private
		 */
		private var _isoBounds:IBounds;

		/**
		 * @inheritDoc
		 */
		public function get isoBounds ():IBounds
		{
			/* if (!_isoBounds || isInvalidated)
				_isoBounds =  */

			return new SceneBounds(this);
		}

		///////////////////////////////////////////////////////////////////////////////
		//	HOST CONTAINER
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * @private
		 */
		protected var host:DisplayObjectContainer;

		as3isolib_internal

		/**
		 * @private
		 */
		public function get hostContainer ():DisplayObjectContainer
		{
			return host;
		}

		/**
		 * @inheritDoc
		 */
		public function set hostContainer (value:DisplayObjectContainer):void
		{
			if (value && host != value)
			{
				if (host && host.contains(container))
				{
					host.removeChild(container);
					ownerObject = null;
				}

				else if (hasParent)
					parent.removeChild(this);

				host = value;
				if (host)
				{
					host.addChild(container);
					ownerObject = host;
					parentNode = null;
				}
			}
		}

		///////////////////////////////////////////////////////////////////////////////
		//	INVALIDATE CHILDREN
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * @private
		 *
		 * Array of invalidated children.  Each child dispatches an IsoEvent.INVALIDATION event which notifies
		 * the scene that that particular child is invalidated and subsequentally the scene is also invalidated.
		 */
		protected var invalidatedChildrenArray:Array = [];

		/**
		 * @inheritDoc
		 */
		public function get invalidatedChildren ():Array
		{
			return invalidatedChildrenArray;
		}

		///////////////////////////////////////////////////////////////////////////////
		//	OVERRIDES
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * @inheritDoc
		 */
		override public function addChildAt (child:INode, index:uint):void
		{
			if (child is IIsoDisplayObject)
			{
				super.addChildAt(child, index);
				child.addEventListener(IsoEvent.INVALIDATE, child_invalidateHandler);

				bIsInvalidated = true; //since the child most likely had fired an invalidation event prior to being added, manually invalidate the scene
			}

			else
				throw new Error ("parameter child is not of type IIsoDisplayObject");
		}

		/**
		 * @inheritDoc
		 */
		override public function setChildIndex (child:INode, index:uint):void
		{
			super.setChildIndex(child, index);
			bIsInvalidated = true;
		}

		/**
		 * @inheritDoc
		 */
		override public function removeChildByID (id:String):INode
		{
			var child:INode = super.removeChildByID(id);
			if (child)
			{
				child.removeEventListener(IsoEvent.INVALIDATE, child_invalidateHandler);
				bIsInvalidated = true;
			}

			return child;
		}

		/**
		 * @inheritDoc
		 */
		override public function removeAllChildren ():void
		{
			var child:INode
			for each (child in children)
				child.removeEventListener(IsoEvent.INVALIDATE, child_invalidateHandler);

			super.removeAllChildren();
			bIsInvalidated = true;
		}

		/**
		 * Renders the scene as invalidated if a child object is invalidated.
		 *
		 * @param evt The IsoEvent dispatched from the invalidated child.
		 */
		protected function child_invalidateHandler (evt:IsoEvent):void
		{
			var child:Object = evt.target;
			if (invalidatedChildrenArray.indexOf(child) == -1)
				invalidatedChildrenArray.push(child);

			bIsInvalidated = true;
		}

		///////////////////////////////////////////////////////////////////////////////
		//	LAYOUT RENDERER
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * Flags the scene for possible layout rendering.
		 * If false, child objects are sorted by the order they were added rather than by their isometric depth.
		 */
		public var layoutEnabled:Boolean = true;

		private var layoutRendererFactory:IFactory;

		/**
		 * @private
		 */
		public function get layoutRenderer ():IFactory
		{
			return layoutRendererFactory;
		}

		/**
		 * The factory used to create the ISceneLayoutRenderer responsible for the layout of the child objects.
		 */
		public function set layoutRenderer (value:IFactory):void
		{
			if (value && layoutRendererFactory != value)
			{
				layoutRendererFactory = value;
				bIsInvalidated = true;
			}
		}

		///////////////////////////////////////////////////////////////////////////////
		//	STYLE RENDERERS
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * Flags the scene for possible style rendering.
		 */
		public var stylingEnabled:Boolean = true;

		private var styleRendererFactories:Array = [];

		/**
		 * @private
		 */
		public function get styleRenderers ():Array
		{
			return styleRendererFactories;
		}

		/**
		 * An array of IFactories whose class generators are ISceneRenderer.
		 * If any value contained within the array is not of type IFactory, it will be ignored.
		 */
		public function set styleRenderers (value:Array):void
		{
			if (value)
			{
				var temp:Array = [];
				var obj:Object;
				for each (obj in value)
				{
					if (obj is IFactory)
						temp.push(obj);
				}

				styleRendererFactories = temp;
				bIsInvalidated = true;
			}
		}

		///////////////////////////////////////////////////////////////////////////////
		//	INVALIDATION
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * Flags the scene as invalidated during the rendering process
		 */
		public function invalidateScene ():void
		{
			bIsInvalidated = true;
		}

		///////////////////////////////////////////////////////////////////////////////
		//	RENDER
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * @inheritDoc
		 */
		override protected function renderLogic (recursive:Boolean = true):void
		{
			super.renderLogic(recursive); //push individual changes thru, then sort based on new visible content of each child

			if (bIsInvalidated)
			{
				//render the layout first
				var sceneLayoutRenderer:ISceneLayoutRenderer;
				if (layoutEnabled)
				{
					sceneLayoutRenderer = layoutRendererFactory.newInstance();
					if (sceneLayoutRenderer)
						sceneLayoutRenderer.renderScene(this);
				}

				//apply styling
				mainContainer.graphics.clear(); //should we do this here?

				var sceneRenderer:ISceneRenderer;
				var factory:IFactory
				if (stylingEnabled)
				{
					for each (factory in styleRendererFactories)
					{
						sceneRenderer = factory.newInstance();
						if (sceneRenderer)
							sceneRenderer.renderScene(this);
					}
				}

				bIsInvalidated = false;
			}
		}

		/**
		 * @inheritDoc
		 */
		override protected function postRenderLogic ():void
		{
			invalidatedChildrenArray = [];

			super.postRenderLogic();
			//should we still call sceneRendered()?
			sceneRendered();
		}

		/**
		 * This function has been deprecated.  Please refer to postRenderLogic.
		 */
		protected function sceneRendered ():void
		{
		}

		///////////////////////////////////////////////////////////////////////////////
		//	CONSTRUCTOR
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * Constructor
		 */
		public function IsoScene ()
		{
			super();

			layoutRendererFactory = new ClassFactory(DefaultSceneLayoutRenderer);
		}
	}
}

/*

as3isolib - An open-source ActionScript 3.0 Isometric Library developed to assist
in creating isometrically projected content (such as games and graphics)
targeted for the Flash player platform

http://code.google.com/p/as3isolib/

Copyright (c) 2006 - 2008 J.W.Opitz, All Rights Reserved.

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 as3isolib.display.scene
{

	import as3isolib.bounds.IBounds;
	import as3isolib.bounds.SceneBounds;
	import as3isolib.core.IIsoDisplayObject;
	import as3isolib.core.IsoContainer;
	import as3isolib.core.as3isolib_internal;
	import as3isolib.data.INode;
	import as3isolib.display.renderers.DefaultSceneLayoutRenderer;
	import as3isolib.display.renderers.ISceneLayoutRenderer;
	import as3isolib.display.renderers.ISceneRenderer;
	import as3isolib.events.IsoEvent;

	import flash.display.DisplayObjectContainer;

	import mx.core.ClassFactory;
	import mx.core.IFactory;

	use namespace as3isolib_internal;

	/**
	 * IsoScene is a base class for grouping and rendering IIsoDisplayObject children according to their isometric position-based depth.
	 */
	public class IsoScene extends IsoContainer implements IIsoScene
	{
		///////////////////////////////////////////////////////////////////////////////
		//	BOUNDS
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * @private
		 */
		private var _isoBounds:IBounds;

		/**
		 * @inheritDoc
		 */
		public function get isoBounds ():IBounds
		{
			/* if (!_isoBounds || isInvalidated)
				_isoBounds =  */

			return new SceneBounds(this);
		}

		///////////////////////////////////////////////////////////////////////////////
		//	HOST CONTAINER
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * @private
		 */
		protected var host:DisplayObjectContainer;

		as3isolib_internal

		/**
		 * @private
		 */
		public function get hostContainer ():DisplayObjectContainer
		{
			return host;
		}

		/**
		 * @inheritDoc
		 */
		public function set hostContainer (value:DisplayObjectContainer):void
		{
			if (value && host != value)
			{
				if (host && host.contains(container))
				{
					host.removeChild(container);
					ownerObject = null;
				}

				else if (hasParent)
					parent.removeChild(this);

				host = value;
				if (host)
				{
					host.addChild(container);
					ownerObject = host;
					parentNode = null;
				}
			}
		}

		///////////////////////////////////////////////////////////////////////////////
		//	INVALIDATE CHILDREN
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * @private
		 *
		 * Array of invalidated children.  Each child dispatches an IsoEvent.INVALIDATION event which notifies
		 * the scene that that particular child is invalidated and subsequentally the scene is also invalidated.
		 */
		protected var invalidatedChildrenArray:Array = [];

		/**
		 * @inheritDoc
		 */
		public function get invalidatedChildren ():Array
		{
			return invalidatedChildrenArray;
		}

		///////////////////////////////////////////////////////////////////////////////
		//	OVERRIDES
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * @inheritDoc
		 */
		override public function addChildAt (child:INode, index:uint):void
		{
			if (child is IIsoDisplayObject)
			{
				super.addChildAt(child, index);
				child.addEventListener(IsoEvent.INVALIDATE, child_invalidateHandler);

				bIsInvalidated = true; //since the child most likely had fired an invalidation event prior to being added, manually invalidate the scene
			}

			else
				throw new Error ("parameter child is not of type IIsoDisplayObject");
		}

		/**
		 * @inheritDoc
		 */
		override public function setChildIndex (child:INode, index:uint):void
		{
			super.setChildIndex(child, index);
			bIsInvalidated = true;
		}

		/**
		 * @inheritDoc
		 */
		override public function removeChildByID (id:String):INode
		{
			var child:INode = super.removeChildByID(id);
			if (child)
			{
				child.removeEventListener(IsoEvent.INVALIDATE, child_invalidateHandler);
				bIsInvalidated = true;
			}

			return child;
		}

		/**
		 * @inheritDoc
		 */
		override public function removeAllChildren ():void
		{
			var child:INode
			for each (child in children)
				child.removeEventListener(IsoEvent.INVALIDATE, child_invalidateHandler);

			super.removeAllChildren();
			bIsInvalidated = true;
		}

		/**
		 * Renders the scene as invalidated if a child object is invalidated.
		 *
		 * @param evt The IsoEvent dispatched from the invalidated child.
		 */
		protected function child_invalidateHandler (evt:IsoEvent):void
		{
			var child:Object = evt.target;
			if (invalidatedChildrenArray.indexOf(child) == -1)
				invalidatedChildrenArray.push(child);

			bIsInvalidated = true;
		}

		///////////////////////////////////////////////////////////////////////////////
		//	LAYOUT RENDERER
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * Flags the scene for possible layout rendering.
		 * If false, child objects are sorted by the order they were added rather than by their isometric depth.
		 */
		public var layoutEnabled:Boolean = true;

		private var layoutRendererFactory:IFactory;

		/**
		 * @private
		 */
		public function get layoutRenderer ():IFactory
		{
			return layoutRendererFactory;
		}

		/**
		 * The factory used to create the ISceneLayoutRenderer responsible for the layout of the child objects.
		 */
		public function set layoutRenderer (value:IFactory):void
		{
			if (value && layoutRendererFactory != value)
			{
				layoutRendererFactory = value;
				bIsInvalidated = true;
			}
		}

		///////////////////////////////////////////////////////////////////////////////
		//	STYLE RENDERERS
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * Flags the scene for possible style rendering.
		 */
		public var stylingEnabled:Boolean = true;

		private var styleRendererFactories:Array = [];

		/**
		 * @private
		 */
		public function get styleRenderers ():Array
		{
			return styleRendererFactories;
		}

		/**
		 * An array of IFactories whose class generators are ISceneRenderer.
		 * If any value contained within the array is not of type IFactory, it will be ignored.
		 */
		public function set styleRenderers (value:Array):void
		{
			if (value)
			{
				var temp:Array = [];
				var obj:Object;
				for each (obj in value)
				{
					if (obj is IFactory)
						temp.push(obj);
				}

				styleRendererFactories = temp;
				bIsInvalidated = true;
			}
		}

		///////////////////////////////////////////////////////////////////////////////
		//	INVALIDATION
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * Flags the scene as invalidated during the rendering process
		 */
		public function invalidateScene ():void
		{
			bIsInvalidated = true;
		}

		///////////////////////////////////////////////////////////////////////////////
		//	RENDER
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * @inheritDoc
		 */
		override protected function renderLogic (recursive:Boolean = true):void
		{
			super.renderLogic(recursive); //push individual changes thru, then sort based on new visible content of each child

			if (bIsInvalidated)
			{
				//render the layout first
				var sceneLayoutRenderer:ISceneLayoutRenderer;
				if (layoutEnabled)
				{
					sceneLayoutRenderer = layoutRendererFactory.newInstance();
					if (sceneLayoutRenderer)
						sceneLayoutRenderer.renderScene(this);
				}

				//fix for bug #20 - http://code.google.com/p/as3isolib/issues/detail?id=20
				var sceneRenderer:ISceneRenderer;
				var factory:IFactory
				if (stylingEnabled && styleRendererFactories.length > 0)
				{
					mainContainer.graphics.clear();

					for each (factory in styleRendererFactories)
					{
						sceneRenderer = factory.newInstance();
						if (sceneRenderer)
							sceneRenderer.renderScene(this);
					}
				}

				bIsInvalidated = false;
			}
		}

		/**
		 * @inheritDoc
		 */
		override protected function postRenderLogic ():void
		{
			invalidatedChildrenArray = [];

			super.postRenderLogic();
			//should we still call sceneRendered()?
			sceneRendered();
		}

		/**
		 * This function has been deprecated.  Please refer to postRenderLogic.
		 */
		protected function sceneRendered ():void
		{
		}

		///////////////////////////////////////////////////////////////////////////////
		//	CONSTRUCTOR
		///////////////////////////////////////////////////////////////////////////////

		/**
		 * Constructor
		 */
		public function IsoScene ()
		{
			super();

			layoutRendererFactory = new ClassFactory(DefaultSceneLayoutRenderer);
		}
	}
}


package aerys.minko.render
{
	import aerys.minko.Minko;
	import aerys.minko.ns.minko;
	import aerys.minko.render.effect.IEffect;
	import aerys.minko.render.effect.basic.BasicEffect;
	import aerys.minko.render.renderer.DefaultRenderer;
	import aerys.minko.render.renderer.IRenderer;
	import aerys.minko.scene.data.LocalData;
	import aerys.minko.scene.data.RenderingData;
	import aerys.minko.scene.data.ViewportData;
	import aerys.minko.scene.node.IScene;
	import aerys.minko.scene.visitor.ISceneVisitor;
	import aerys.minko.scene.visitor.PostprocessVisitor;
	import aerys.minko.scene.visitor.RenderingVisitor;
	import aerys.minko.scene.visitor.WorldDataVisitor;
	import aerys.minko.type.Factory;
	import aerys.minko.type.IVersionnable;

	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.display.Stage3D;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.display3D.Context3DRenderMode;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.utils.Dictionary;
	import flash.utils.getTimer;

	/**
	 * The viewport is the the display area used to render a 3D scene.
	 * It can be used to render any IScene3D object.
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Viewport extends Sprite implements IVersionnable
	{
		use namespace minko;

		private static const ZERO2		: Point						= new Point();

		private var _version			: uint						= 0;

		private var _width				: Number					= 0.;
		private var _height				: Number					= 0.;
		private var _autoResize			: Boolean					= false;
		private var _antiAliasing		: int						= 0;

		private var _visitors			: Vector.<ISceneVisitor>	= null;

		private var _time				: int						= 0;
		private var _sceneSize			: uint						= 0;
		private var _drawTime			: int						= 0;

		private var _stage3d			: Stage3D					= null;
		private var _rendererClass		: Class						= null;
		private var _renderer			: IRenderer					= null;
		private var _defaultEffect		: IEffect					= new BasicEffect();
		private var _backgroundColor	: int						= 0;

		private var _postProcessEffect	: IEffect					= null;
		private var _postProcessVisitor	: ISceneVisitor				= new PostprocessVisitor();

		private var _viewportData		: ViewportData				= null;

		private var _logoIsHidden		: Boolean					= false;

		public function get postProcessEffect() : IEffect
		{
			return _postProcessEffect;
		}

		public function set postProcessEffect(value : IEffect):void
		{
			_postProcessEffect = value;
		}

		public function get version() : uint
		{
			return _version;
		}

		override public function set x(value : Number) : void
		{
			super.x = value;
			updateRectangle();
		}

		override public function set y(value : Number) : void
		{
			super.y = value;
			updateRectangle();
		}

		/**
		 * Indicates the width of the viewport.
		 * @return The width of the viewport.
		 *
		 */
		override public function get width()	: Number
		{
			return _width;
		}

		override public function set width(value : Number) : void
		{
			if (value != _width)
			{
				_width = value;
				++_version;

				resetStage3D();
			}
		}

		public function get sceneSize() : uint
		{
			return _sceneSize;
		}

		/**
		 * Indicates the height of the viewport.
		 * @return The height of the viewport.
		 *
		 */
		override public function get height() : Number
		{
			return _height;
		}

		override public function set height(value : Number) : void
		{
			if (value != _height)
			{
				_height = value;
				++_version;

				resetStage3D();
			}
		}

		/**
		 * The anti-aliasing value used to render the scene.
		 *
		 * @return
		 *
		 */
		public function get antiAliasing() : int
		{
			return _antiAliasing;
		}

		public function set antiAliasing(value : int) : void
		{
			if (value != _antiAliasing)
			{
				_antiAliasing = value;
				++_version;

				resetStage3D();
			}
		}

		public function get defaultEffect() : IEffect
		{
			return _defaultEffect;
		}

		public function set defaultEffect(value : IEffect) : void
		{
			_defaultEffect = value;
		}

		/**
		 * The amount of triangle rendered durung the last call to the
		 * "render" method. Sometimes, the number of triangles is higher
		 * than the total amount of triangles in the scene because some
		 * triangles are renderer multiple times (multipass).
		 *
		 * @return
		 *
		 */
		public function get numTriangles() : uint
		{
			return _renderer ? _renderer.numTriangles : 0;
		}

		/**
		 * The time spent during the last call to the "render" method.
		 *
		 * This time includes:
		 *

		 *
updating the scene graph

		 *
rendering the scene graph

		 *
performing draw calls to the internal 3D APIs

		 *

		 *
		 * @return
		 *
		 */
		public function get renderingTime() : uint
		{
			return _time;
		}

		public function get drawingTime() : int
		{
			return _drawTime;
		}

		public function get renderMode() : String
		{
			return _stage3d && _stage3d.context3D ? _stage3d.context3D.driverInfo : null;
		}

		public function get backgroundColor() : int
		{
			return _backgroundColor;
		}

		public function set backgroundColor(value : int) : void
		{
			_backgroundColor = value;
		}

		public function get visitors() : Vector.<ISceneVisitor>
		{
			return _visitors;
		}

		/**
		 * Creates a new Viewport object.
		 *
		 * @param width The width of the viewport.
		 * @param height The height of the viewport.
		 */
		public function Viewport(width			: uint		= 0,
								 height			: uint		= 0,
								 autoResize		: Boolean	= true,
								 antiAliasing	: int		= 0,
								 rendererType	: Class 	= null)
		{
			this.width = width;
			this.height = height;

			_autoResize		= autoResize;
			_antiAliasing	= antiAliasing;
			_rendererClass	= rendererType || DefaultRenderer;
			_viewportData	= new ViewportData(this);

			addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
			addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
			addEventListener(Event.ADDED, addedHandler);
		}

		private function addedToStageHandler(event : Event) : void
		{
			var stageId	: int 		= 0;

			_stage3d = stage.stage3Ds[stageId];

			while (_stage3d.willTrigger(Event.CONTEXT3D_CREATE))
				_stage3d = stage.stage3Ds[int(++stageId)];

			_stage3d.addEventListener(Event.CONTEXT3D_CREATE, resetStage3D);
			_stage3d.requestContext3D(Context3DRenderMode.AUTO);

			if (!_logoIsHidden)
				showLogo();
		}

		private function removedFromStage(event : Event) : void
		{
			_stage3d.removeEventListener(Event.CONTEXT3D_CREATE, resetStage3D);
			_stage3d.context3D.dispose();
			_stage3d = null;
		}

		private function addedHandler(event : Event) : void
		{
			if (_autoResize)
			{
				parent.addEventListener(Event.RESIZE, resizeHandler);
				if (parent == stage)
				{
					stage.align = StageAlign.TOP_LEFT;
					stage.scaleMode = StageScaleMode.NO_SCALE;
				}
			}

			updateRectangle();
		}

		private function resizeHandler(event : Event = null) : void
		{
			if (parent == stage)
			{
				width = stage.stageWidth;
				height = stage.stageHeight;
			}
			else
			{
				var p : DisplayObject = parent;

				while (p && (p.width == 0 || p.height == 0))
					p = p.parent;

				if (p)
				{
					width = p.width;
					height = p.height;
				}
			}

			resetStage3D();

			if (!_logoIsHidden)
				showLogo();
		}

		private function resetStage3D(event : Event = null) : void
		{
			if (_stage3d && _stage3d.context3D && _width && _height)
			{
				updateRectangle();

				_renderer = new _rendererClass(this, _stage3d.context3D);

				_visitors = Vector.<ISceneVisitor>([
					new WorldDataVisitor(),
					new RenderingVisitor()
				]);

				dispatchEvent(new Event(Event.INIT));
			}
		}

		private function updateRectangle() : void
		{
			if (_stage3d)
			{
				var origin : Point = localToGlobal(ZERO2);

				_stage3d.x = origin.x;
				_stage3d.y = origin.y;

				if (_stage3d.context3D)
				{
					_stage3d.context3D.configureBackBuffer(
						Math.min(2048, _width),
						Math.min(2048, _height),
						_antiAliasing,
						true
					);
				}
			}
		}

		/**
		 * Render the specified scene.
		 * @param scene
		 */
		public function render(scene : IScene) : void
		{
			if (!_logoIsHidden)
				showLogo();

			if (_visitors && _visitors.length != 0)
			{
				var time : Number = getTimer();

				// create the data sources the visitors are going to write and read from during render.
				var localData		: LocalData		= new LocalData();
				var worldData		: Dictionary	= new Dictionary();
				var renderingData	: RenderingData	= new RenderingData();

				// push viewport related data into the data sources
				worldData[ViewportData] = _viewportData;
				renderingData.effect = defaultEffect;

				// execute all visitors
				for each (var visitor : ISceneVisitor in _visitors)
					visitor.processSceneGraph(scene, localData, worldData, renderingData, _renderer);

				_drawTime	= _renderer.drawingTime;

				// execute postprocessing
				if (_postProcessEffect != null)
				{
					renderingData.effect = _postProcessEffect;
					_postProcessVisitor.processSceneGraph(scene, localData, worldData, renderingData, _renderer);
				}

				_renderer.present();

				_sceneSize	= visitors[0].numNodes;
				_time		= getTimer() - time;
				_drawTime	+= _renderer.drawingTime;
			}
			else
			{
				_time = 0;
				_drawTime = 0;
			}

			Factory.sweep();
		}

		public function showLogo() : void
		{
			var logo : Sprite = Minko.logo;

			addChild(logo);

			logo.x = 5;
			logo.y = _height - logo.height - 5;
		}

		public function hideLogo() : void
		{
			_logoIsHidden = true;
			if (contains(Minko.logo))
				removeChild(Minko.logo);
		}
	}
}

package aerys.minko.render
{
	import aerys.minko.Minko;
	import aerys.minko.ns.minko;
	import aerys.minko.render.effect.IEffect;
	import aerys.minko.render.effect.basic.BasicEffect;
	import aerys.minko.render.renderer.DefaultRenderer;
	import aerys.minko.render.renderer.IRenderer;
	import aerys.minko.scene.data.LocalData;
	import aerys.minko.scene.data.RenderingData;
	import aerys.minko.scene.data.ViewportData;
	import aerys.minko.scene.node.IScene;
	import aerys.minko.scene.visitor.ISceneVisitor;
	import aerys.minko.scene.visitor.PostprocessVisitor;
	import aerys.minko.scene.visitor.RenderingVisitor;
	import aerys.minko.scene.visitor.WorldDataVisitor;
	import aerys.minko.type.Factory;
	import aerys.minko.type.IVersionnable;

	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.display.Stage3D;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.display3D.Context3DRenderMode;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.utils.Dictionary;
	import flash.utils.getTimer;

	/**
	 * The viewport is the the display area used to render a 3D scene.
	 * It can be used to render any IScene3D object.
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Viewport extends Sprite implements IVersionnable
	{
		use namespace minko;

		private static const ZERO2		: Point						= new Point();

		private var _version			: uint						= 0;

		private var _width				: Number					= 0.;
		private var _height				: Number					= 0.;
		private var _autoResize			: Boolean					= false;
		private var _antiAliasing		: int						= 0;

		private var _visitors			: Vector.<ISceneVisitor>	= null;

		private var _time				: int						= 0;
		private var _sceneSize			: uint						= 0;
		private var _drawTime			: int						= 0;

		private var _stage3d			: Stage3D					= null;
		private var _rendererClass		: Class						= null;
		private var _renderer			: IRenderer					= null;
		private var _defaultEffect		: IEffect					= new BasicEffect();
		private var _backgroundColor	: int						= 0;

		private var _postProcessEffect	: IEffect					= null;
		private var _postProcessVisitor	: ISceneVisitor				= new PostprocessVisitor();

		private var _viewportData		: ViewportData				= null;

		private var _logoIsHidden		: Boolean					= false;

		public function get postProcessEffect() : IEffect
		{
			return _postProcessEffect;
		}

		public function set postProcessEffect(value : IEffect):void
		{
			_postProcessEffect = value;
		}

		public function get version() : uint
		{
			return _version;
		}

		override public function set x(value : Number) : void
		{
			super.x = value;
			updateRectangle();
		}

		override public function set y(value : Number) : void
		{
			super.y = value;
			updateRectangle();
		}

		/**
		 * Indicates the width of the viewport.
		 * @return The width of the viewport.
		 *
		 */
		override public function get width()	: Number
		{
			return _width;
		}

		override public function set width(value : Number) : void
		{
			if (value != _width)
			{
				_width = value;
				++_version;

				resetStage3D();
			}
		}

		public function get frameId() : uint
		{
			return _renderer.frameId;
		}

		public function get sceneSize() : uint
		{
			return _sceneSize;
		}

		/**
		 * Indicates the height of the viewport.
		 * @return The height of the viewport.
		 *
		 */
		override public function get height() : Number
		{
			return _height;
		}

		override public function set height(value : Number) : void
		{
			if (value != _height)
			{
				_height = value;
				++_version;

				resetStage3D();
			}
		}

		/**
		 * The anti-aliasing value used to render the scene.
		 *
		 * @return
		 *
		 */
		public function get antiAliasing() : int
		{
			return _antiAliasing;
		}

		public function set antiAliasing(value : int) : void
		{
			if (value != _antiAliasing)
			{
				_antiAliasing = value;
				++_version;

				resetStage3D();
			}
		}

		public function get defaultEffect() : IEffect
		{
			return _defaultEffect;
		}

		public function set defaultEffect(value : IEffect) : void
		{
			_defaultEffect = value;
		}

		/**
		 * The amount of triangle rendered durung the last call to the
		 * "render" method. Sometimes, the number of triangles is higher
		 * than the total amount of triangles in the scene because some
		 * triangles are renderer multiple times (multipass).
		 *
		 * @return
		 *
		 */
		public function get numTriangles() : uint
		{
			return _renderer ? _renderer.numTriangles : 0;
		}

		/**
		 * The time spent during the last call to the "render" method.
		 *
		 * This time includes:
		 *

		 *
updating the scene graph

		 *
rendering the scene graph

		 *
performing draw calls to the internal 3D APIs

		 *

		 *
		 * @return
		 *
		 */
		public function get renderingTime() : uint
		{
			return _time;
		}

		public function get drawingTime() : int
		{
			return _drawTime;
		}

		public function get renderMode() : String
		{
			return _stage3d && _stage3d.context3D ? _stage3d.context3D.driverInfo : null;
		}

		public function get backgroundColor() : int
		{
			return _backgroundColor;
		}

		public function set backgroundColor(value : int) : void
		{
			_backgroundColor = value;
		}

		public function get visitors() : Vector.<ISceneVisitor>
		{
			return _visitors;
		}

		/**
		 * Creates a new Viewport object.
		 *
		 * @param width The width of the viewport.
		 * @param height The height of the viewport.
		 */
		public function Viewport(width			: uint		= 0,
								 height			: uint		= 0,
								 autoResize		: Boolean	= true,
								 antiAliasing	: int		= 0,
								 rendererType	: Class 	= null)
		{
			this.width = width;
			this.height = height;

			_autoResize		= autoResize;
			_antiAliasing	= antiAliasing;
			_rendererClass	= rendererType || DefaultRenderer;
			_viewportData	= new ViewportData(this);

			addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
			addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
			addEventListener(Event.ADDED, addedHandler);
		}

		private function addedToStageHandler(event : Event) : void
		{
			var stageId	: int 		= 0;

			_stage3d = stage.stage3Ds[stageId];

			while (_stage3d.willTrigger(Event.CONTEXT3D_CREATE))
				_stage3d = stage.stage3Ds[int(++stageId)];

			_stage3d.addEventListener(Event.CONTEXT3D_CREATE, resetStage3D);
			_stage3d.requestContext3D(Context3DRenderMode.AUTO);

			if (!_logoIsHidden)
				showLogo();
		}

		private function removedFromStage(event : Event) : void
		{
			_stage3d.removeEventListener(Event.CONTEXT3D_CREATE, resetStage3D);
			_stage3d.context3D.dispose();
			_stage3d = null;
		}

		private function addedHandler(event : Event) : void
		{
			if (_autoResize)
			{
				parent.addEventListener(Event.RESIZE, resizeHandler);
				if (parent == stage)
				{
					stage.align = StageAlign.TOP_LEFT;
					stage.scaleMode = StageScaleMode.NO_SCALE;
				}
			}

			updateRectangle();
		}

		private function resizeHandler(event : Event = null) : void
		{
			if (parent == stage)
			{
				width = stage.stageWidth;
				height = stage.stageHeight;
			}
			else
			{
				var p : DisplayObject = parent;

				while (p && (p.width == 0 || p.height == 0))
					p = p.parent;

				if (p)
				{
					width = p.width;
					height = p.height;
				}
			}

			resetStage3D();

			if (!_logoIsHidden)
				showLogo();
		}

		private function resetStage3D(event : Event = null) : void
		{
			if (_stage3d && _stage3d.context3D && _width && _height)
			{
				updateRectangle();

				_renderer = new _rendererClass(this, _stage3d.context3D);

				_visitors = Vector.<ISceneVisitor>([
					new WorldDataVisitor(),
					new RenderingVisitor()
				]);

				dispatchEvent(new Event(Event.INIT));
			}
		}

		private function updateRectangle() : void
		{
			if (_stage3d)
			{
				var origin : Point = localToGlobal(ZERO2);

				_stage3d.x = origin.x;
				_stage3d.y = origin.y;

				if (_stage3d.context3D)
				{
					_stage3d.context3D.configureBackBuffer(
						Math.min(2048, _width),
						Math.min(2048, _height),
						_antiAliasing,
						true
					);
				}
			}
		}

		/**
		 * Render the specified scene.
		 * @param scene
		 */
		public function render(scene : IScene) : void
		{
			if (!_logoIsHidden)
				showLogo();

			if (_visitors && _visitors.length != 0)
			{
				var time : Number = getTimer();

				// create the data sources the visitors are going to write and read from during render.
				var localData		: LocalData		= new LocalData();
				var worldData		: Dictionary	= new Dictionary();
				var renderingData	: RenderingData	= new RenderingData();

				// push viewport related data into the data sources
				worldData[ViewportData] = _viewportData;
				renderingData.effect = defaultEffect;

				// execute all visitors
				for each (var visitor : ISceneVisitor in _visitors)
					visitor.processSceneGraph(scene, localData, worldData, renderingData, _renderer);

				_drawTime	= _renderer.drawingTime;

				// execute postprocessing
				if (_postProcessEffect != null)
				{
					renderingData.effect = _postProcessEffect;
					_postProcessVisitor.processSceneGraph(scene, localData, worldData, renderingData, _renderer);
				}

				_renderer.present();

				_sceneSize	= visitors[0].numNodes;
				_time		= getTimer() - time;
				_drawTime	+= _renderer.drawingTime;
			}
			else
			{
				_time = 0;
				_drawTime = 0;
			}

			Factory.sweep();
		}

		public function showLogo() : void
		{
			var logo : Sprite = Minko.logo;

			addChild(logo);

			logo.x = 5;
			logo.y = _height - logo.height - 5;
		}

		public function hideLogo() : void
		{
			_logoIsHidden = true;
			if (contains(Minko.logo))
				removeChild(Minko.logo);
		}
	}
}

Add a getter to get the frameId from the viewport


//
// Flump - Copyright 2012 Three Rings Design

package flump.test {

import flash.desktop.NativeApplication;
import flash.filesystem.File;

import flump.executor.Executor;
import flump.executor.Finisher;
import flump.executor.Future;

import starling.display.Sprite;

import com.threerings.util.Log;
import com.threerings.util.Map;
import com.threerings.util.Maps;

public class TestRunner extends Sprite
{
    public static const root :File = new File(File.applicationDirectory.nativePath);
    public static const resources :File = root.resolvePath('../src/test/resources');
    public static const dist :File = root.resolvePath('../dist');

    public function TestRunner () {
        Log.setLevel("", Log.INFO);
        _exec.completed.add(onCompletion);
        _exec.terminated.add(function (..._) :void {
            if (_passed.length > 0) {
                trace("Passed:");
                for each (var name :String in _passed) trace("  " + name);
            }
            if (_failed.length > 0) {
                trace("Failed:");
                for each (name in _failed) trace("  " + name);
            }
            NativeApplication.nativeApplication.exit(_failed.length == 0 ? 0 : 1);
        });
        new XflParseTest(this);
    }

    public function run (name :String, f :Function) :void {
        runAsync(name, function (finisher :Finisher) :void { finisher.succeedAfter(f); });
    }

    public function runAsync (name :String, f :Function) :void { _runs.put(_exec.submit(f), name); }

    protected function onCompletion (f :Future) :void {
        const name :String = _runs.remove(f);
        if (name == null) {
            log.error("Unknown test completed", "future", f, "result", f.result);
            return;
        }
        if (f.isSuccessful) {
            log.info("Passed", "test", name);
            _passed.push(name);
        } else {
            _failed.push(name)
            if (f.result is Error) log.error("Failed", "test", name, f.result);
            else log.error("Failed", "test", name, "reason", f.result);
        }
        if (_exec.isIdle) _exec.shutdown();
    }

    protected const _exec :Executor = new Executor(/*maxSimultaneous=*/1);
    protected const _runs :Map = Maps.newMapOf(Future);//String name

    protected const _passed :Vector.<String> = new Vector.<String>();
    protected const _failed :Vector.<String> = new Vector.<String>();

    private static const log :Log = Log.getLog(TestRunner);
}
}

//
// Flump - Copyright 2012 Three Rings Design

package flump.test {

import flash.desktop.NativeApplication;
import flash.filesystem.File;

import flump.executor.Executor;
import flump.executor.Finisher;
import flump.executor.Future;

import starling.display.Sprite;

import com.threerings.util.Log;
import com.threerings.util.Map;
import com.threerings.util.Maps;

public class TestRunner extends Sprite
{
    public static const root :File = new File(File.applicationDirectory.nativePath);
    public static const resources :File = root.resolvePath('../src/test/resources');
    public static const dist :File = root.resolvePath('../dist');

    public function TestRunner () {
        Log.setLevel("", Log.INFO);
        _exec.completed.add(onCompletion);
        _exec.terminated.add(function (..._) :void {
            if (_passed.length > 0) {
                trace("Passed:");
                for each (var name :String in _passed) trace("  " + name);
            }
            if (_failed.length > 0) {
                trace("Failed:");
                for each (name in _failed) trace("  " + name);
            }
            NativeApplication.nativeApplication.exit(_failed.length == 0 ? 0 : 1);
        });
        new XflParseTest(this);
    }

    public function run (name :String, f :Function) :void {
        runAsync(name, function (finisher :Finisher) :void { finisher.succeedAfter(f); });
    }

    public function runAsync (name :String, f :Function) :void { _runs.put(_exec.submit(f), name); }

    protected function onCompletion (f :Future) :void {
        const name :String = _runs.remove(f);
        if (name == null) {
            log.error("Unknown test completed", "future", f, "result", f.result);
            return;
        }
        if (f.isSuccessful) {
            log.info("Passed", "test", name);
            _passed.push(name);
        } else {
            _failed.push(name)
            if (f.result is Error) log.error("Failed", "test", name, f.result);
            else log.error("Failed", "test", name, "reason", f.result);
            _exec.shutdownNow();
        }
        if (_exec.isIdle) _exec.shutdown();
    }

    protected const _exec :Executor = new Executor(/*maxSimultaneous=*/1);
    protected const _runs :Map = Maps.newMapOf(Future);//String name

    protected const _passed :Vector.<String> = new Vector.<String>();
    protected const _failed :Vector.<String> = new Vector.<String>();

    private static const log :Log = Log.getLog(TestRunner);
}
}

Halt tests after a failure

Halt tests after a failure


//
// Flump - Copyright 2012 Three Rings Design

package flump.display {

import flump.mold.MovieMold;

import org.osflash.signals.Signal;

import starling.core.Starling;
import starling.display.DisplayObject;
import starling.display.Sprite;
import starling.events.Event;

public class Movie extends Sprite
{
    public static const FIRST_FRAME :String = "flump.movie.FIRST_FRAME";
    public static const LAST_FRAME :String = "flump.movie.LAST_FRAME";

    public const labelPassed :Signal = new Signal(String);

    public function Movie (src :MovieMold, frameRate :Number, idToDisplayObject :Function) {
        name = src.libraryItem;
        _labels = src.labels;
        _frameRate = frameRate;
        _ticker = new Ticker(advanceTime);
        const flipbook :Boolean = src.flipbook;
        if (src.flipbook) {
            _layers = new Vector.<Layer>(1, true);
            _layers[0] = new Layer(this, src.layers[0], idToDisplayObject, /*flipbook=*/true);
            _frames = src.layers[0].frames;
        } else {
            _layers = new Vector.<Layer>(src.layers.length, true);
            for (var ii :int = 0; ii < _layers.length; ii++) {
                _layers[ii] = new Layer(this, src.layers[ii], idToDisplayObject, /*flipbook=*/false);
                _frames = Math.max(src.layers[ii].frames, _frames);
            }
        }
        _duration = _frames / _frameRate;
        goto(0, true, false);
        addEventListener(Event.ADDED_TO_STAGE, addedToStage);
        addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
    }

    public function get frame () :int { return _frame; }

    public function get frames () :int { return _frames; }

    protected function advanceTime (dt :Number) :void {
        if (!_playing) return;

        _playTime += dt;
        var actualPlaytime :Number = _playTime;
        if (_playTime > _duration) _playTime = _playTime % _duration;
        var newFrame :int = int(_playTime * _frameRate);
        const overDuration :Boolean = dt >= _duration;
        // If the update crosses or goes to the stopFrame, go to the stop frame, stop the movie and
        // clear it
        if (_stopFrame != NO_FRAME) {
            // how many frames remain to the stopframe?
            var framesRemaining :int =
                (_frame <= _stopFrame ? _stopFrame - _frame : _frames - _frame + _stopFrame);
            var framesElapsed :int = int(actualPlaytime * _frameRate) - _frame;
            if (framesElapsed >= framesRemaining) {
                _playing = false;
                newFrame = _stopFrame;
                _stopFrame = NO_FRAME;
            }
        }
        goto(newFrame, false, overDuration);
    }

    protected function goto (newFrame :int, fromSkip :Boolean, overDuration :Boolean) :void {
        if (_goingToFrame) {
            _pendingFrame = newFrame;
            return;
        }
        _goingToFrame = true;
        const differentFrame :Boolean = newFrame != _frame;
        const wrapped :Boolean = newFrame < _frame;
        if (differentFrame) {
            if (wrapped) {
                for each (var layer :Layer in _layers) {
                    layer.changedKeyframe = true;
                    layer.keyframeIdx = 0;
                }
            }
            for each (layer in _layers) layer.drawFrame(newFrame);
        }

        // Update the frame before firing, so if firing changes the frame, it sticks.
        const oldFrame :int = _frame;
        _frame = newFrame;
        if (fromSkip) {
            fireLabels(newFrame, newFrame);
            _playTime = newFrame/_frameRate;
        } else if (overDuration) {
            fireLabels(oldFrame + 1, _frames - 1);
            fireLabels(0, _frame);
        } else if (differentFrame) {
            if (wrapped) {
                fireLabels(oldFrame + 1, _frames - 1);
                fireLabels(0, _frame);
            } else {
                fireLabels(oldFrame + 1, _frame);
            }
        }
        _goingToFrame = false;
        if (_pendingFrame != NO_FRAME) {
            newFrame = _pendingFrame;
            _pendingFrame = NO_FRAME;
            goto(newFrame, true, false);
        }

    }

    protected function fireLabels (startFrame :int, endFrame :int) :void {
        for (var ii :int = startFrame; ii <= endFrame; ii++) {
            if (_labels[ii] == null) continue;
            for each (var label :String in _labels[ii]) labelPassed.dispatch(label);
        }
    }

    protected function addedToStage (..._) :void { Starling.juggler.add(_ticker); }

    protected function removedFromStage (..._) :void { Starling.juggler.add(_ticker); }

    protected var _goingToFrame :Boolean;
    protected var _pendingFrame :int = NO_FRAME;
    protected var _frame :int = NO_FRAME, _stopFrame :int = NO_FRAME;
    protected var _playing :Boolean = true;
    protected var _playTime :Number, _duration :Number;
    protected var _layers :Vector.<Layer>;
    protected var _ticker :Ticker;
    protected var _frames :int;
    protected var _frameRate :Number;
    protected var _labels :Vector.<Vector.<String>>;

    private static const NO_FRAME :int = -1;
}
}
import flump.display.Movie;
import flump.mold.KeyframeMold;
import flump.mold.LayerMold;

import starling.display.DisplayObject;
import starling.display.Sprite;

class Layer {
    public var keyframeIdx :int ;// The index of the last keyframe drawn in drawFrame
    public var layerIdx :int;// This layer's index in the movie
    public var keyframes :Vector.<KeyframeMold>;
    // Only created if there are multiple items on this layer. If it does exist, the appropriate display is swapped in at keyframe changes. If it doesn't, the display is only added to the parent on layer creation
    public var displays :Vector.<DisplayObject>;// <SPDisplayObject*>
    public var movie :Movie; // The movie this layer belongs to
    // If the keyframe has changed since the last drawFrame
    public var changedKeyframe :Boolean;

    public function Layer (movie :Movie, src :LayerMold, idToDisplayObject :Function,
            flipbook :Boolean) {
        keyframes = src.keyframes;
        this.movie = movie;
        var lastItem :String;
        for (var ii :int = 0; ii < keyframes.length && lastItem == null; ii++) {
            lastItem = keyframes[ii].id;
        }
        if (!flipbook && lastItem == null) movie.addChild(new Sprite());// Label only layer
        else {
            var multipleItems :Boolean = flipbook;
            for (ii = 0; ii < keyframes.length && !multipleItems; ii++) {
                multipleItems = keyframes[ii].id != lastItem;
            }
            if (!multipleItems) movie.addChild(idToDisplayObject(lastItem));
            else {
                displays = new Vector.<DisplayObject>();
                for each (var kf :KeyframeMold in keyframes) {
                    var display :DisplayObject = kf.id == null ? new Sprite() : idToDisplayObject(kf.id);
                    displays.push(display);
                    display.name = src.name;
                }
                movie.addChild(displays[0]);
            }
        }
        layerIdx = movie.numChildren - 1;
        movie.getChildAt(layerIdx).name = src.name;
    }

    public function drawFrame (frame :int) :void {
        while (keyframeIdx < keyframes.length - 1 && keyframes[keyframeIdx + 1].index <= frame) {
            keyframeIdx++;
            changedKeyframe = true;
        }
        // We've got multiple items. Swap in the one for this kf
        if (changedKeyframe && displays != null) {
            movie.removeChildAt(layerIdx);
            movie.addChildAt(displays[keyframeIdx], layerIdx);
        }
        changedKeyframe = false;

        const kf :KeyframeMold = keyframes[keyframeIdx];
        const layer :DisplayObject = movie.getChildAt(layerIdx);
        if (keyframeIdx == keyframes.length - 1 || kf.index == frame) {
            layer.x = kf.x;
            layer.y = kf.y;
            layer.scaleX = kf.scaleX;
            layer.scaleY = kf.scaleY;
            layer.rotation = kf.rotation;
            layer.alpha = kf.alpha;
        } else {
            var interped :Number = (frame - kf.index)/kf.duration;
            var ease :Number = kf.ease;
            if (ease != 0) {
                var t :Number;
                if (ease < 0) {
                    // Ease in
                    var inv :Number = 1 - interped;
                    t = 1 - inv*inv;
                    ease = -ease;
                } else {
                    // Ease out
                    t = interped*interped;
                }
                interped = ease*t + (1 - ease)*interped;
            }

            const nextKf :KeyframeMold = keyframes[keyframeIdx + 1];
            layer.x = kf.x + (nextKf.x - kf.x) * interped;
            layer.y = kf.y + (nextKf.y - kf.y) * interped;
            layer.scaleX = kf.scaleX + (nextKf.scaleX - kf.scaleX) * interped;
            layer.scaleY = kf.scaleY + (nextKf.scaleY - kf.scaleY) * interped;
            layer.rotation = kf.rotation + (nextKf.rotation - kf.rotation) * interped;
            layer.alpha = kf.alpha + (nextKf.alpha - kf.alpha) * interped;
        }

        layer.pivotX = kf.pivotX;
        layer.pivotY = kf.pivotY;
        layer.visible = kf.visible;
    }
}

import starling.animation.IAnimatable;

class Ticker implements IAnimatable {
    public function Ticker (callback :Function) {
        _callback = callback;
    }

    public function get isComplete () :Boolean { return false; }

    public function advanceTime (time :Number) :void { _callback(time); }

    protected var _callback :Function;
}

//
// Flump - Copyright 2012 Three Rings Design

package flump.display {

import flump.mold.MovieMold;

import org.osflash.signals.Signal;

import starling.core.Starling;
import starling.display.DisplayObject;
import starling.display.Sprite;
import starling.events.Event;

public class Movie extends Sprite
{
    public static const FIRST_FRAME :String = "flump.movie.FIRST_FRAME";
    public static const LAST_FRAME :String = "flump.movie.LAST_FRAME";

    public const labelPassed :Signal = new Signal(String);

    public function Movie (src :MovieMold, frameRate :Number, idToDisplayObject :Function) {
        name = src.libraryItem;
        _labels = src.labels;
        _frameRate = frameRate;
        _ticker = new Ticker(advanceTime);
        const flipbook :Boolean = src.flipbook;
        if (src.flipbook) {
            _layers = new Vector.<Layer>(1, true);
            _layers[0] = new Layer(this, src.layers[0], idToDisplayObject, /*flipbook=*/true);
            _frames = src.layers[0].frames;
        } else {
            _layers = new Vector.<Layer>(src.layers.length, true);
            for (var ii :int = 0; ii < _layers.length; ii++) {
                _layers[ii] = new Layer(this, src.layers[ii], idToDisplayObject, /*flipbook=*/false);
                _frames = Math.max(src.layers[ii].frames, _frames);
            }
        }
        _duration = _frames / _frameRate;
        goto(0, true, false);
        addEventListener(Event.ADDED_TO_STAGE, addedToStage);
        addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
    }

    public function get frame () :int { return _frame; }

    public function get frames () :int { return _frames; }

    protected function advanceTime (dt :Number) :void {
        if (!_playing) return;

        _playTime += dt;
        var actualPlaytime :Number = _playTime;
        if (_playTime > _duration) _playTime = _playTime % _duration;
        var newFrame :int = int(_playTime * _frameRate);
        const overDuration :Boolean = dt >= _duration;
        // If the update crosses or goes to the stopFrame, go to the stop frame, stop the movie and
        // clear it
        if (_stopFrame != NO_FRAME) {
            // how many frames remain to the stopframe?
            var framesRemaining :int =
                (_frame <= _stopFrame ? _stopFrame - _frame : _frames - _frame + _stopFrame);
            var framesElapsed :int = int(actualPlaytime * _frameRate) - _frame;
            if (framesElapsed >= framesRemaining) {
                _playing = false;
                newFrame = _stopFrame;
                _stopFrame = NO_FRAME;
            }
        }
        goto(newFrame, false, overDuration);
    }

    protected function goto (newFrame :int, fromSkip :Boolean, overDuration :Boolean) :void {
        if (_goingToFrame) {
            _pendingFrame = newFrame;
            return;
        }
        _goingToFrame = true;
        const differentFrame :Boolean = newFrame != _frame;
        const wrapped :Boolean = newFrame < _frame;
        if (differentFrame) {
            if (wrapped) {
                for each (var layer :Layer in _layers) {
                    layer.changedKeyframe = true;
                    layer.keyframeIdx = 0;
                }
            }
            for each (layer in _layers) layer.drawFrame(newFrame);
        }

        // Update the frame before firing, so if firing changes the frame, it sticks.
        const oldFrame :int = _frame;
        _frame = newFrame;
        if (fromSkip) {
            fireLabels(newFrame, newFrame);
            _playTime = newFrame/_frameRate;
        } else if (overDuration) {
            fireLabels(oldFrame + 1, _frames - 1);
            fireLabels(0, _frame);
        } else if (differentFrame) {
            if (wrapped) {
                fireLabels(oldFrame + 1, _frames - 1);
                fireLabels(0, _frame);
            } else {
                fireLabels(oldFrame + 1, _frame);
            }
        }
        _goingToFrame = false;
        if (_pendingFrame != NO_FRAME) {
            newFrame = _pendingFrame;
            _pendingFrame = NO_FRAME;
            goto(newFrame, true, false);
        }

    }

    protected function fireLabels (startFrame :int, endFrame :int) :void {
        for (var ii :int = startFrame; ii <= endFrame; ii++) {
            if (_labels[ii] == null) continue;
            for each (var label :String in _labels[ii]) labelPassed.dispatch(label);
        }
    }

    protected function addedToStage (..._) :void { Starling.juggler.add(_ticker); }

    protected function removedFromStage (..._) :void { Starling.juggler.remove(_ticker); }

    protected var _goingToFrame :Boolean;
    protected var _pendingFrame :int = NO_FRAME;
    protected var _frame :int = NO_FRAME, _stopFrame :int = NO_FRAME;
    protected var _playing :Boolean = true;
    protected var _playTime :Number, _duration :Number;
    protected var _layers :Vector.<Layer>;
    protected var _ticker :Ticker;
    protected var _frames :int;
    protected var _frameRate :Number;
    protected var _labels :Vector.<Vector.<String>>;

    private static const NO_FRAME :int = -1;
}
}
import flump.display.Movie;
import flump.mold.KeyframeMold;
import flump.mold.LayerMold;

import starling.display.DisplayObject;
import starling.display.Sprite;

class Layer {
    public var keyframeIdx :int ;// The index of the last keyframe drawn in drawFrame
    public var layerIdx :int;// This layer's index in the movie
    public var keyframes :Vector.<KeyframeMold>;
    // Only created if there are multiple items on this layer. If it does exist, the appropriate display is swapped in at keyframe changes. If it doesn't, the display is only added to the parent on layer creation
    public var displays :Vector.<DisplayObject>;// <SPDisplayObject*>
    public var movie :Movie; // The movie this layer belongs to
    // If the keyframe has changed since the last drawFrame
    public var changedKeyframe :Boolean;

    public function Layer (movie :Movie, src :LayerMold, idToDisplayObject :Function,
            flipbook :Boolean) {
        keyframes = src.keyframes;
        this.movie = movie;
        var lastItem :String;
        for (var ii :int = 0; ii < keyframes.length && lastItem == null; ii++) {
            lastItem = keyframes[ii].id;
        }
        if (!flipbook && lastItem == null) movie.addChild(new Sprite());// Label only layer
        else {
            var multipleItems :Boolean = flipbook;
            for (ii = 0; ii < keyframes.length && !multipleItems; ii++) {
                multipleItems = keyframes[ii].id != lastItem;
            }
            if (!multipleItems) movie.addChild(idToDisplayObject(lastItem));
            else {
                displays = new Vector.<DisplayObject>();
                for each (var kf :KeyframeMold in keyframes) {
                    var display :DisplayObject = kf.id == null ? new Sprite() : idToDisplayObject(kf.id);
                    displays.push(display);
                    display.name = src.name;
                }
                movie.addChild(displays[0]);
            }
        }
        layerIdx = movie.numChildren - 1;
        movie.getChildAt(layerIdx).name = src.name;
    }

    public function drawFrame (frame :int) :void {
        while (keyframeIdx < keyframes.length - 1 && keyframes[keyframeIdx + 1].index <= frame) {
            keyframeIdx++;
            changedKeyframe = true;
        }
        // We've got multiple items. Swap in the one for this kf
        if (changedKeyframe && displays != null) {
            movie.removeChildAt(layerIdx);
            movie.addChildAt(displays[keyframeIdx], layerIdx);
        }
        changedKeyframe = false;

        const kf :KeyframeMold = keyframes[keyframeIdx];
        const layer :DisplayObject = movie.getChildAt(layerIdx);
        if (keyframeIdx == keyframes.length - 1 || kf.index == frame) {
            layer.x = kf.x;
            layer.y = kf.y;
            layer.scaleX = kf.scaleX;
            layer.scaleY = kf.scaleY;
            layer.rotation = kf.rotation;
            layer.alpha = kf.alpha;
        } else {
            var interped :Number = (frame - kf.index)/kf.duration;
            var ease :Number = kf.ease;
            if (ease != 0) {
                var t :Number;
                if (ease < 0) {
                    // Ease in
                    var inv :Number = 1 - interped;
                    t = 1 - inv*inv;
                    ease = -ease;
                } else {
                    // Ease out
                    t = interped*interped;
                }
                interped = ease*t + (1 - ease)*interped;
            }

            const nextKf :KeyframeMold = keyframes[keyframeIdx + 1];
            layer.x = kf.x + (nextKf.x - kf.x) * interped;
            layer.y = kf.y + (nextKf.y - kf.y) * interped;
            layer.scaleX = kf.scaleX + (nextKf.scaleX - kf.scaleX) * interped;
            layer.scaleY = kf.scaleY + (nextKf.scaleY - kf.scaleY) * interped;
            layer.rotation = kf.rotation + (nextKf.rotation - kf.rotation) * interped;
            layer.alpha = kf.alpha + (nextKf.alpha - kf.alpha) * interped;
        }

        layer.pivotX = kf.pivotX;
        layer.pivotY = kf.pivotY;
        layer.visible = kf.visible;
    }
}

import starling.animation.IAnimatable;

class Ticker implements IAnimatable {
    public function Ticker (callback :Function) {
        _callback = callback;
    }

    public function get isComplete () :Boolean { return false; }

    public function advanceTime (time :Number) :void { _callback(time); }

    protected var _callback :Function;
}

Remove the juggler when removed

Remove the juggler when removed


package
{
	import cc.milkshape.framework.Application;
	import cc.milkshape.main.*;
	import cc.milkshape.preloader.PreloaderKb;
	import cc.milkshape.preloader.events.PreloaderEvent;
	import cc.milkshape.register.Register;
	import cc.milkshape.user.Login;
	import cc.milkshape.utils.Constance;
	import cc.milkshape.utils.MilkshapeMenu;
	import cc.milkshape.utils.TableLine;

	import flash.display.Shape;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.ColorTransform;

	import nl.demonsters.debugger.MonsterDebugger;

	[SWF(width='1430', height='680', frameRate='31', backgroundColor='#191919')]

	public class Main extends Application
	{
		private static var _instance:Main = null;
		private const DEFAULT_CONTAINER_POSX:int = 20;
		private const DEFAULT_CONTAINER_POSY:int = 100;
		private const BAR_BG_COLOR:int = 0x0a0a0a;
		private var _equalizer:Equalizer;
		private var _menu:Menu;
		private var _subMenu:SubMenu;
		private var _login:Login;
		private var _logo:Logo;
		private var _fullscreen:Fullscreen;
		private var _pageContainer:PreloaderKb;
		private var _bottomBar:Shape;
		private var _topBar:Shape;
		private var _background:TableLine;
		private var _register:Register;

		public function Main():void {
			if(_instance != null)
				throw new Error("Cannot instance this class a second time, use getInstance instead.");
			_instance = this;
			var debugger:MonsterDebugger = new MonsterDebugger(this);
			addEventListener(Event.ADDED_TO_STAGE, _handlerAddedToStage);
		}

		public static function getInstance():Main {
			if(_instance == null)
				new Main();
			return _instance;
		}

		private function _handlerAddedToStage(e:Event):void
		{
			var mct:MilkshapeMenu = new MilkshapeMenu();// Menu contextuel personnalisé
			contextMenu = mct.cm;

			stage.align = StageAlign.TOP_LEFT;
        	stage.scaleMode = StageScaleMode.NO_SCALE;
        	stage.addEventListener(Event.RESIZE, _resize);

			_menu = new Menu(new Array(
				{label: 'home', slug: 'home', url: Constance.HOME_SWF, posX:0, posY:60},
				{label: 'about', slug: 'about', url: Constance.ABOUT_SWF},
				{label: 'issues', slug: 'issues', url: Constance.ISSUES_SWF, posX:0},
				{label: 'artists', slug: 'artists', url: Constance.ARTISTS_SWF},
				{label: 'contact', slug: 'contact', url: Constance.CONTACT_SWF}
			));
			_menu.addEventListener(PreloaderEvent.LOAD, loadSwf);

			_subMenu = new SubMenu();
			_subMenu.addEventListener(PreloaderEvent.LOAD, loadSwf);

			_fullscreen = new Fullscreen();

			_equalizer = new Equalizer();

			_login = new Login();

			_logo = new Logo();
			_logo.addEventListener(MouseEvent.CLICK, _showRegister);

			_bottomBar = new Shape();
			_bottomBar.graphics.beginFill(BAR_BG_COLOR);
			_bottomBar.graphics.drawRect(0, 0, stage.stageWidth, 33);
			_bottomBar.graphics.endFill();

			_topBar = new Shape();
			_topBar.graphics.beginFill(BAR_BG_COLOR);
			_topBar.graphics.drawRect(0, 0, stage.stageWidth, 60);
			_topBar.graphics.endFill();

			var errorArea:ErrorArea = new ErrorArea();

			_pageContainer = new PreloaderKb();

			_background = new TableLine(stage.stageWidth*2, stage.stageHeight*2, 100, 100, 0x202020);

            // On colore les éléments du main
            var mainColorTransform:ColorTransform = new ColorTransform();
			mainColorTransform.color = 0xffdd00;
			_logo.transform.colorTransform = mainColorTransform;
			mainColorTransform.color = 0x999999;
			_fullscreen.transform.colorTransform = mainColorTransform;
			_equalizer.transform.colorTransform = mainColorTransform;

			addChild(_pageContainer);
			addChild(_bottomBar);
			addChild(_topBar);
			addChild(_menu);
			addChild(_subMenu);
			addChild(_login);
			addChild(_logo);
			addChild(_fullscreen);
			addChild(_equalizer);
			addChild(errorArea);

			_itemsDisposition();

			loadSwf(new PreloaderEvent(PreloaderEvent.LOAD, _menu.getMenuButton('home').option));
		}

		private function _showRegister(e:Event):void
		{
			_register = new Register();
			_register.addEventListener('CLOSE_REGISTER', _closeRegister);
			addChild(_register);
			removeChild(_login);
		}

		private function _closeRegister(e:Event):void
		{
			_register.removeEventListener('CLOSE_REGISTER', _closeRegister);
			if(contains(_register))
			{
				removeChild(_register);
				addChild(_login);
			}
		}

		public function loadSwf(e:PreloaderEvent):void
		{
			if((e.option.background != null) ? e.option.background : true)
				addChildAt(_background, 0);
			else if(contains(_background))
				removeChild(_background);

			_pageContainer.x = (e.option.posX != null) ? e.option.posX : DEFAULT_CONTAINER_POSX;
			_pageContainer.y = (e.option.posY != null) ? e.option.posY : DEFAULT_CONTAINER_POSY;
			trace(_pageContainer.y);
			try {
				_pageContainer.unloadMedia();
			} catch(e:Error) {
				trace(e.message);
			}

			try {
				_pageContainer.params = e.option.params;
				_pageContainer.loadMedia(e.option.url);
			} catch(e:Error){
				trace(e.message);
			}
		}

		private function _itemsDisposition():void
		{
			ErrorArea.getInstance().x = 610;
			ErrorArea.getInstance().y = 24;
			_pageContainer.y = 60;
			_background.x = -50;
			_menu.x = 37;
			_logo.x = 37;
			_logo.y = 12;
			_login.x = 275;
			_login.y = 24;
			_fullscreen.y = 12;
			_equalizer.y = _fullscreen.y + 20;
			_resize();
		}

		private function _resize(e:Event = null):void
		{
			_topBar.width = stage.stageWidth;

			_bottomBar.y = stage.stageHeight - 33;
			_bottomBar.width = stage.stageWidth;

			_fullscreen.x = stage.stageWidth - 27;
			_equalizer.x = _fullscreen.x;

			_menu.y = stage.stageHeight - 21;

			_subMenu.y = stage.stageHeight - 23;
			_subMenu.x = stage.stageWidth - 70;
		}

	}
}

package
{
	import cc.milkshape.main.*;
	import cc.milkshape.preloader.PreloaderKb;
	import cc.milkshape.preloader.events.PreloaderEvent;
	import cc.milkshape.register.Register;
	import cc.milkshape.user.Login;
	import cc.milkshape.utils.Constance;
	import cc.milkshape.utils.MilkshapeMenu;
	import cc.milkshape.utils.TableLine;

	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.ColorTransform;

	import nl.demonsters.debugger.MonsterDebugger;

	[SWF(width='1430', height='680', frameRate='31', backgroundColor='#191919')]

	public class Main extends Sprite
	{
		private static var _instance:Main = null;
		private const DEFAULT_CONTAINER_POSX:int = 20;
		private const DEFAULT_CONTAINER_POSY:int = 100;
		private const BAR_BG_COLOR:int = 0x0a0a0a;
		private var _equalizer:Equalizer;
		private var _menu:Menu;
		private var _subMenu:SubMenu;
		private var _login:Login;
		private var _logo:Logo;
		private var _fullscreen:Fullscreen;
		private var _pageContainer:PreloaderKb;
		private var _bottomBar:Shape;
		private var _topBar:Shape;
		private var _background:TableLine;
		private var _register:Register;

		public function Main():void {
			if(_instance != null)
				throw new Error("Cannot instance this class a second time, use getInstance instead.");
			_instance = this;
			var debugger:MonsterDebugger = new MonsterDebugger(this);
			addEventListener(Event.ADDED_TO_STAGE, _handlerAddedToStage);
		}

		public static function getInstance():Main {
			if(_instance == null)
				new Main();
			return _instance;
		}

		private function _handlerAddedToStage(e:Event):void
		{
			var mct:MilkshapeMenu = new MilkshapeMenu();// Menu contextuel personnalisé
			contextMenu = mct.cm;

			stage.align = StageAlign.TOP_LEFT;
        	stage.scaleMode = StageScaleMode.NO_SCALE;
        	stage.addEventListener(Event.RESIZE, _resize);

			_menu = new Menu(new Array(
				{label: 'home', slug: 'home', url: Constance.HOME_SWF, posX:0, posY:60},
				{label: 'about', slug: 'about', url: Constance.ABOUT_SWF},
				{label: 'issues', slug: 'issues', url: Constance.ISSUES_SWF, posX:0},
				{label: 'artists', slug: 'artists', url: Constance.ARTISTS_SWF},
				{label: 'contact', slug: 'contact', url: Constance.CONTACT_SWF}
			));
			_menu.addEventListener(PreloaderEvent.LOAD, loadSwf);

			_subMenu = new SubMenu();
			_subMenu.addEventListener(PreloaderEvent.LOAD, loadSwf);

			_fullscreen = new Fullscreen();

			_equalizer = new Equalizer();

			_login = new Login();

			_logo = new Logo();
			_logo.addEventListener(MouseEvent.CLICK, _showRegister);

			_bottomBar = new Shape();
			_bottomBar.graphics.beginFill(BAR_BG_COLOR);
			_bottomBar.graphics.drawRect(0, 0, stage.stageWidth, 33);
			_bottomBar.graphics.endFill();

			_topBar = new Shape();
			_topBar.graphics.beginFill(BAR_BG_COLOR);
			_topBar.graphics.drawRect(0, 0, stage.stageWidth, 60);
			_topBar.graphics.endFill();

			var errorArea:ErrorArea = new ErrorArea();

			_pageContainer = new PreloaderKb();

			_background = new TableLine(stage.stageWidth*2, stage.stageHeight*2, 100, 100, 0x202020);

            // On colore les éléments du main
            var mainColorTransform:ColorTransform = new ColorTransform();
			mainColorTransform.color = 0xffdd00;
			_logo.transform.colorTransform = mainColorTransform;
			mainColorTransform.color = 0x999999;
			_fullscreen.transform.colorTransform = mainColorTransform;
			_equalizer.transform.colorTransform = mainColorTransform;

			addChild(_pageContainer);
			addChild(_bottomBar);
			addChild(_topBar);
			addChild(_menu);
			addChild(_subMenu);
			addChild(_login);
			addChild(_logo);
			addChild(_fullscreen);
			addChild(_equalizer);
			addChild(errorArea);

			_itemsDisposition();

			loadSwf(new PreloaderEvent(PreloaderEvent.LOAD, _menu.getMenuButton('home').option));
		}

		private function _showRegister(e:Event):void
		{
			_register = new Register();
			_register.addEventListener('CLOSE_REGISTER', _closeRegister);
			addChild(_register);
			removeChild(_login);
		}

		private function _closeRegister(e:Event):void
		{
			_register.removeEventListener('CLOSE_REGISTER', _closeRegister);
			if(contains(_register))
			{
				removeChild(_register);
				addChild(_login);
			}
		}

		public function loadSwf(e:PreloaderEvent):void
		{
			if((e.option.background != null) ? e.option.background : true)
				addChildAt(_background, 0);
			else if(contains(_background))
				removeChild(_background);

			_pageContainer.x = (e.option.posX != null) ? e.option.posX : DEFAULT_CONTAINER_POSX;
			_pageContainer.y = (e.option.posY != null) ? e.option.posY : DEFAULT_CONTAINER_POSY;
			trace(_pageContainer.y);
			try {
				_pageContainer.unloadMedia();
			} catch(e:Error) {
				trace(e.message);
			}

			try {
				_pageContainer.params = e.option.params;
				_pageContainer.loadMedia(e.option.url);
			} catch(e:Error){
				trace(e.message);
			}
		}

		private function _itemsDisposition():void
		{
			ErrorArea.getInstance().x = 610;
			ErrorArea.getInstance().y = 24;
			_pageContainer.y = 60;
			_background.x = -50;
			_menu.x = 37;
			_logo.x = 37;
			_logo.y = 12;
			_login.x = 275;
			_login.y = 24;
			_fullscreen.y = 12;
			_equalizer.y = _fullscreen.y + 20;
			_resize();
		}

		private function _resize(e:Event = null):void
		{
			_topBar.width = stage.stageWidth;

			_bottomBar.y = stage.stageHeight - 33;
			_bottomBar.width = stage.stageWidth;

			_fullscreen.x = stage.stageWidth - 27;
			_equalizer.x = _fullscreen.x;

			_menu.y = stage.stageHeight - 21;

			_subMenu.y = stage.stageHeight - 23;
			_subMenu.x = stage.stageWidth - 70;
		}

	}
}

fix Main

fix Main


class A {
  static protected function get staticGetA() {
    return 10;
  }
  protected function get getA() {
    return 0;
  }
  static protected function set staticSetA(v) {
    trace ("staticSetA " + v);
  }
}
class B extends A {
  static protected function get staticGetB() {
    return 11;
  }
  protected function get getB() {
    return 1;
  }

  static protected function set staticSetB(v) {
    trace ("staticSetB " + v);
  }
}
class C extends B {
  static protected function get staticGetC() {
    return 12;
  }
  protected function get getC() {
    return 2;
  }
  static protected function set staticSetC(v) {
    trace ("staticSetC " + v);
  }

  public function foo() {
    trace(getA + getB + getC);
    trace(staticGetA + staticGetB + staticGetC);

    staticSetA = "A";
    staticSetB = "B";
    staticSetC = "C";
  }
}

var c = new C();
c.foo();

trace("--");

class A {
  static protected function get staticGetA() {
    return 10;
  }
  protected function get getA() {
    return 0;
  }
  protected function set setA(v) {
    trace ("setA " + v);
  }
  static protected function set staticSetA(v) {
    trace ("staticSetA " + v);
  }
}
class B extends A {
  static protected function get staticGetB() {
    return 11;
  }
  protected function get getB() {
    return 1;
  }
  protected function set setB(v) {
    trace ("setB " + v);
  }
  static protected function set staticSetB(v) {
    trace ("staticSetB " + v);
  }
}
class C extends B {
  static protected function get staticGetC() {
    return 12;
  }
  protected function get getC() {
    return 2;
  }
  protected function set setC(v) {
    trace ("setC " + v);
  }
  static protected function set staticSetC(v) {
    trace ("staticSetC " + v);
  }

  public function foo() {
    trace(getA + getB + getC);
    setA = "A";
    setB = "B";
    setC = "C";

    trace(staticGetA + staticGetB + staticGetC);
    staticSetA = "A";
    staticSetB = "B";
    staticSetC = "C";
  }
}

var c = new C();
c.foo();

trace("--");

Update test case.

Update test case.


package
{
	import com.kaltura.hls.HLSPluginInfo;
    import com.kaltura.kdpfl.model.MediaProxy;
    import com.kaltura.kdpfl.plugin.IPlugin;
    import com.kaltura.kdpfl.plugin.IPluginFactory;
    import flash.utils.getDefinitionByName;

    import org.osmf.events.MediaFactoryEvent;
    import org.osmf.media.MediaFactory;
    import org.osmf.media.MediaResourceBase;
    import org.osmf.media.PluginInfoResource;
    import org.puremvc.as3.interfaces.IFacade;
    import com.kaltura.kdpfl.plugin.KPluginEvent;

	import flash.display.Sprite;

	import org.osmf.media.PluginInfo;
    import flash.system.Security;

	public class KalturaHLSPlugin extends Sprite implements IPluginFactory, IPlugin
	{
		private var _pluginInfo:HLSPluginInfo;
        private static const HLS_PLUGIN_INFO:String = "com.kaltura.hls.HLSPluginInfo";

        public function KalturaHLSPlugin()
        {
            Security.allowDomain("*");
            _pluginInfo = new HLSPluginInfo();
        }

        public function create (pluginName : String =null) : IPlugin
        {
            return this;
        }

        public function initializePlugin(facade:IFacade):void
        {
            //Getting Static reference to Plugin.
            var pluginInfoRef:Class = getDefinitionByName(HLS_PLUGIN_INFO) as Class;
            var pluginResource:MediaResourceBase = new PluginInfoResource(new pluginInfoRef);

            var mediaFactory:MediaFactory = (facade.retrieveProxy(MediaProxy.NAME) as MediaProxy).vo.mediaFactory;
            mediaFactory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD, onOSMFPluginLoaded);
            mediaFactory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD_ERROR, onOSMFPluginLoadError);
            mediaFactory.loadPlugin(pluginResource);
        }

        /**
         * Listener for the LOAD_COMPLETE event.
         * @param e - MediaFactoryEvent
         *
         */
        protected function onOSMFPluginLoaded (e : MediaFactoryEvent) : void
        {
            e.target.removeEventListener(MediaFactoryEvent.PLUGIN_LOAD, onOSMFPluginLoaded);
            dispatchEvent( new KPluginEvent (KPluginEvent.KPLUGIN_INIT_COMPLETE) );
        }
        /**
         * Listener for the LOAD_ERROR event.
         * @param e - MediaFactoryEvent
         *
         */
        protected function onOSMFPluginLoadError (e : MediaFactoryEvent) : void
        {
            e.target.removeEventListener(MediaFactoryEvent.PLUGIN_LOAD_ERROR, onOSMFPluginLoadError);
            dispatchEvent( new KPluginEvent (KPluginEvent.KPLUGIN_INIT_FAILED) );
        }

        public function setSkin(styleName:String, setSkinSize:Boolean=false):void
        {
            // Do nothing here
        }

		public function get pluginInfo():PluginInfo
		{
			return _pluginInfo;
		}
	}
}

package
{
	import com.kaltura.hls.HLSPluginInfo;
    import com.kaltura.kdpfl.model.MediaProxy;
    import com.kaltura.kdpfl.plugin.IPlugin;
    import com.kaltura.kdpfl.plugin.IPluginFactory;
    import flash.utils.getDefinitionByName;

    import org.osmf.events.MediaFactoryEvent;
    import org.osmf.media.MediaFactory;
    import org.osmf.media.MediaResourceBase;
    import org.osmf.media.PluginInfoResource;
    import org.puremvc.as3.interfaces.IFacade;
    import com.kaltura.kdpfl.plugin.KPluginEvent;

	import flash.display.Sprite;

	import org.osmf.media.PluginInfo;
    import flash.system.Security;

	public class KalturaHLSPlugin extends Sprite implements IPluginFactory, IPlugin
	{
		private var _pluginInfo:HLSPluginInfo;
        private static const HLS_PLUGIN_INFO:String = "com.kaltura.hls.HLSPluginInfo";
		private var _pluginResource:MediaResourceBase;

        public function KalturaHLSPlugin()
        {
            Security.allowDomain("*");
            _pluginInfo = new HLSPluginInfo();
        }

        public function create (pluginName : String =null) : IPlugin
        {
            return this;
        }

        public function initializePlugin(facade:IFacade):void
        {
            //Getting Static reference to Plugin.
            var pluginInfoRef:Class = getDefinitionByName(HLS_PLUGIN_INFO) as Class;
			_pluginResource = new PluginInfoResource(new pluginInfoRef);

            var mediaFactory:MediaFactory = (facade.retrieveProxy(MediaProxy.NAME) as MediaProxy).vo.mediaFactory;
            mediaFactory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD, onOSMFPluginLoaded);
            mediaFactory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD_ERROR, onOSMFPluginLoadError);
            mediaFactory.loadPlugin(_pluginResource);
        }

        /**
         * Listener for the LOAD_COMPLETE event.
         * @param e - MediaFactoryEvent
         *
         */
        protected function onOSMFPluginLoaded (e : MediaFactoryEvent) : void
        {
			if ( e.resource && e.resource == _pluginResource ) {
				e.target.removeEventListener(MediaFactoryEvent.PLUGIN_LOAD, onOSMFPluginLoaded);
				dispatchEvent( new KPluginEvent (KPluginEvent.KPLUGIN_INIT_COMPLETE) );
			}

        }
        /**
         * Listener for the LOAD_ERROR event.
         * @param e - MediaFactoryEvent
         *
         */
        protected function onOSMFPluginLoadError (e : MediaFactoryEvent) : void
        {
			if ( e.resource && e.resource == _pluginResource ) {
	            e.target.removeEventListener(MediaFactoryEvent.PLUGIN_LOAD_ERROR, onOSMFPluginLoadError);
	            dispatchEvent( new KPluginEvent (KPluginEvent.KPLUGIN_INIT_FAILED) );
			}
        }

        public function setSkin(styleName:String, setSkinSize:Boolean=false):void
        {
            // Do nothing here
        }

		public function get pluginInfo():PluginInfo
		{
			return _pluginInfo;
		}
	}
}

Fix plugin loaded events

Fix plugin loaded events