package aerys.minko.type.loader
{
	import aerys.minko.render.resource.texture.TextureResource;
	import aerys.minko.type.Signal;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.getQualifiedClassName;

	public class TextureLoader implements ILoader
	{
		private static const EMPTY_BITMAPDATA	: BitmapData	= new BitmapData(1, 1, false, 0);

		private var _mipMapping	: Boolean;

		private var _progress	: Signal;
		private var _error		: Signal;
		private var _complete	: Signal;

		private var _isComplete	: Boolean;

		protected var _textureResource	: TextureResource;

		public function get progress() : Signal
		{
			return _progress;
		}

		public function get error() : Signal
		{
			return _error;
		}

		public function get complete() : Signal
		{
			return _complete;
		}

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

		public function get textureResource() : TextureResource
		{
			return _textureResource;
		}

		public function TextureLoader(enableMipmapping : Boolean = true)
		{
			_mipMapping	= enableMipmapping;

			initialize();
		}

		private function initialize() : void
		{
			_textureResource 	= new TextureResource();
			_textureResource.setContentFromBitmapData(EMPTY_BITMAPDATA, _mipMapping);

			_isComplete 		= false;
			_error				= new Signal('TextureLoader.error');
			_progress			= new Signal('TextureLoader.progress');
			_complete			= new Signal('TextureLoader.complete');
		}

		public function load(request : URLRequest) : void
		{
			var loader : URLLoader = new URLLoader();

			loader.dataFormat = URLLoaderDataFormat.BINARY;
			loader.addEventListener(ProgressEvent.PROGRESS, loadProgressHandler);
			loader.addEventListener(Event.COMPLETE, loadCompleteHandler);
			loader.addEventListener(IOErrorEvent.IO_ERROR, loadIoErrorHandler);
			loader.load(request);
		}

		private function loadIoErrorHandler(e : IOErrorEvent) : void
		{
			_textureResource = null;
			_error.execute(this, e.errorID, e.text);
		}

		private function loadProgressHandler(e : ProgressEvent) : void
		{
			_progress.execute(this, e.bytesLoaded, e.bytesTotal);
		}

		private function loadCompleteHandler(e : Event) : void
		{
			loadBytes(URLLoader(e.currentTarget).data);
		}

		public function loadClass(classObject : Class) : void
		{
			var assetObject : Object		= new classObject();

			if (assetObject is Bitmap || assetObject is BitmapData)
			{
				var bitmapData : BitmapData = assetObject as BitmapData;

				if (bitmapData == null)
					bitmapData = Bitmap(assetObject).bitmapData;

				_textureResource.setContentFromBitmapData(bitmapData, _mipMapping);
				bitmapData.dispose();

				_isComplete = true;
				_complete.execute(this, _textureResource);
			}
			else if (assetObject is ByteArray)
			{
				loadBytes(ByteArray(assetObject));
			}
			else
			{
				var className : String = getQualifiedClassName(classObject);
				className = className.substr(className.lastIndexOf(':') + 1);

				_isComplete = true;

				throw new Error('No texture can be created from an object of type \'' + className + '\'');
			}
		}

		public function loadBytes(bytes : ByteArray) : void
		{
			bytes.position = 0;

			if (bytes.readByte() == 'A'.charCodeAt(0) &&
				bytes.readByte() == 'T'.charCodeAt(0) &&
				bytes.readByte() == 'F'.charCodeAt(0))
			{
				bytes.position = 0;
				_textureResource.setContentFromATF(bytes);
				_isComplete = true;
				_complete.execute(this, _textureResource);
			}
			else
			{
				bytes.position = 0;

				var loader : Loader = new Loader();

				loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadBytesCompleteHandler);
				loader.loadBytes(bytes);
			}
		}

		private function loadBytesCompleteHandler(e : Event) : void
		{
			var displayObject : DisplayObject = LoaderInfo(e.currentTarget).content;

			if (displayObject is Bitmap)
			{
				var bitmapData : BitmapData = Bitmap(displayObject).bitmapData;

				_textureResource.setContentFromBitmapData(bitmapData, _mipMapping);
				bitmapData.dispose();

				_isComplete = true;
				_complete.execute(this, _textureResource);
			}
			else
			{
				var className : String = getQualifiedClassName(displayObject);

				className = className.substr(className.lastIndexOf(':') + 1);
				_isComplete = true;

				throw new Error(
					'No texture can be created from an object of type \'' + className + '\''
				);
			}
		}

		public static function loadClass(classObject 		: Class,
										 enableMipMapping 	: Boolean = true) : TextureResource
		{
			var textureLoader : TextureLoader = new TextureLoader(enableMipMapping);

			textureLoader.loadClass(classObject);

			return textureLoader.textureResource;
		}

		public static function load(request				: URLRequest,
									enableMipMapping 	: Boolean = true) : TextureResource
		{
			var textureLoader : TextureLoader = new TextureLoader(enableMipMapping);

			textureLoader.load(request);

			return textureLoader.textureResource;
		}

		public static function loadBytes(bytes				: ByteArray,
										 enableMipMapping 	: Boolean = true) : TextureResource
		{
			var textureLoader : TextureLoader = new TextureLoader(enableMipMapping);

			textureLoader.loadBytes(bytes);

			return textureLoader.textureResource;
		}
	}
}

package aerys.minko.type.loader
{
	import aerys.minko.render.resource.texture.TextureResource;
	import aerys.minko.type.Signal;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.getQualifiedClassName;

	public class TextureLoader implements ILoader
	{
		private static const EMPTY_BITMAPDATA	: BitmapData	= new BitmapData(1, 1, false, 0);

		private var _mipMapping	: Boolean;

		private var _progress	: Signal;
		private var _error		: Signal;
		private var _complete	: Signal;

		private var _isComplete	: Boolean;

		protected var _textureResource	: TextureResource;

		public function get progress() : Signal
		{
			return _progress;
		}

		public function get error() : Signal
		{
			return _error;
		}

		public function get complete() : Signal
		{
			return _complete;
		}

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

		public function get textureResource() : TextureResource
		{
			return _textureResource;
		}

		public function TextureLoader(enableMipmapping : Boolean = true)
		{
			_mipMapping	= enableMipmapping;

			initialize();
		}

		private function initialize() : void
		{
			_textureResource 	= new TextureResource();
			_textureResource.setContentFromBitmapData(EMPTY_BITMAPDATA, _mipMapping);

			_isComplete 		= false;
			_error				= new Signal('TextureLoader.error');
			_progress			= new Signal('TextureLoader.progress');
			_complete			= new Signal('TextureLoader.complete');
		}

		public function load(request : URLRequest) : void
		{
			var loader : URLLoader = new URLLoader();

			loader.dataFormat = URLLoaderDataFormat.BINARY;
			loader.addEventListener(ProgressEvent.PROGRESS, loadProgressHandler);
			loader.addEventListener(Event.COMPLETE, loadCompleteHandler);
			loader.addEventListener(IOErrorEvent.IO_ERROR, loadIoErrorHandler);
			loader.load(request);
		}

		private function loadIoErrorHandler(e : IOErrorEvent) : void
		{
			_textureResource = null;

			if (_error.numCallbacks == 0)
				throw e;
			else
				_error.execute(this, e.errorID, e.text);
		}

		private function loadProgressHandler(e : ProgressEvent) : void
		{
			_progress.execute(this, e.bytesLoaded, e.bytesTotal);
		}

		private function loadCompleteHandler(e : Event) : void
		{
			loadBytes(URLLoader(e.currentTarget).data);
		}

		public function loadClass(classObject : Class) : void
		{
			var assetObject : Object		= new classObject();

			if (assetObject is Bitmap || assetObject is BitmapData)
			{
				var bitmapData : BitmapData = assetObject as BitmapData;

				if (bitmapData == null)
					bitmapData = Bitmap(assetObject).bitmapData;

				_textureResource.setContentFromBitmapData(bitmapData, _mipMapping);
				bitmapData.dispose();

				_isComplete = true;
				_complete.execute(this, _textureResource);
			}
			else if (assetObject is ByteArray)
			{
				loadBytes(ByteArray(assetObject));
			}
			else
			{
				var className : String = getQualifiedClassName(classObject);
				className = className.substr(className.lastIndexOf(':') + 1);

				_isComplete = true;

				throw new Error('No texture can be created from an object of type \'' + className + '\'');
			}
		}

		public function loadBytes(bytes : ByteArray) : void
		{
			bytes.position = 0;

			if (bytes.readByte() == 'A'.charCodeAt(0) &&
				bytes.readByte() == 'T'.charCodeAt(0) &&
				bytes.readByte() == 'F'.charCodeAt(0))
			{
				bytes.position = 0;
				_textureResource.setContentFromATF(bytes);
				_isComplete = true;
				_complete.execute(this, _textureResource);
			}
			else
			{
				bytes.position = 0;

				var loader : Loader = new Loader();

				loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadBytesCompleteHandler);
				loader.loadBytes(bytes);
			}
		}

		private function loadBytesCompleteHandler(e : Event) : void
		{
			var displayObject : DisplayObject = LoaderInfo(e.currentTarget).content;

			if (displayObject is Bitmap)
			{
				var bitmapData : BitmapData = Bitmap(displayObject).bitmapData;

				_textureResource.setContentFromBitmapData(bitmapData, _mipMapping);
				bitmapData.dispose();

				_isComplete = true;
				_complete.execute(this, _textureResource);
			}
			else
			{
				var className : String = getQualifiedClassName(displayObject);

				className = className.substr(className.lastIndexOf(':') + 1);
				_isComplete = true;

				throw new Error(
					'No texture can be created from an object of type \'' + className + '\''
				);
			}
		}

		public static function loadClass(classObject 		: Class,
										 enableMipMapping 	: Boolean = true) : TextureResource
		{
			var textureLoader : TextureLoader = new TextureLoader(enableMipMapping);

			textureLoader.loadClass(classObject);

			return textureLoader.textureResource;
		}

		public static function load(request				: URLRequest,
									enableMipMapping 	: Boolean = true) : TextureResource
		{
			var textureLoader : TextureLoader = new TextureLoader(enableMipMapping);

			textureLoader.load(request);

			return textureLoader.textureResource;
		}

		public static function loadBytes(bytes				: ByteArray,
										 enableMipMapping 	: Boolean = true) : TextureResource
		{
			var textureLoader : TextureLoader = new TextureLoader(enableMipMapping);

			textureLoader.loadBytes(bytes);

			return textureLoader.textureResource;
		}
	}
}

fix TextureLoader.ioErrorHandler() to throw the error if no callback is set for the TextureLoader.error signal


package com.axis.mjpegclient {

  import flash.events.ErrorEvent;
  import flash.events.Event;
  import flash.events.EventDispatcher;
  import flash.events.IOErrorEvent;
  import flash.events.ProgressEvent;
  import flash.events.SecurityErrorEvent;
  import flash.net.Socket;
  import flash.utils.ByteArray;

  import com.axis.Logger;
  import com.axis.ErrorManager;
  import com.axis.http.request;

  [Event(name="image",type="flash.events.Event")]
  [Event(name="connect",type="flash.events.Event")]
  [Event(name="error",type="flash.events.Event")]

  public class Handle extends EventDispatcher {

    private var urlParsed:Object;
    private var socket:Socket = null;
    private var buffer:ByteArray = null;
    private var dataBuffer:ByteArray = null;
    private var url:String = "";
    private var params:Object;
    private var parseHeaders:Boolean = true;
    private var headers:Vector.<String> = new Vector.<String>();
    private var clen:int;
    private var parseSubheaders:Boolean = true;

    public var image:ByteArray = null;

    public function Handle(urlParsed:Object) {
      this.urlParsed = urlParsed;
      this.buffer = new ByteArray();
      this.dataBuffer = new ByteArray();
      this.socket = new Socket();
      this.socket.timeout = 5000;
      this.socket.addEventListener(Event.CONNECT, onConnect);
      this.socket.addEventListener(Event.CLOSE, onClose);
      this.socket.addEventListener(ProgressEvent.SOCKET_DATA, onHttpHeaders);
      this.socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
      this.socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
    }

    private function onError(e:ErrorEvent):void {
      disconnect();
      dispatchEvent(new Event("IOError:" + e.errorID));
    }

    public function disconnect():void {
      if (!socket.connected) {
        return;
      }

      socket.close();
      image = null;
      buffer = null;
      dispatchEvent(new Event("disconnect"));
    }

    public function stop():void {
      disconnect();
    }

    public function connect():void {
      if (socket.connected) {
        disconnect();
      }

      Logger.log('MJPEGClient: connecting to', urlParsed.host + ':' + urlParsed.port);
      socket.connect(urlParsed.host, urlParsed.port);
    }

    private function onConnect(event:Event):void {
      buffer = new ByteArray();
      dataBuffer = new ByteArray();

      headers.length = 0;
      parseHeaders = true;
      parseSubheaders = true;
      socket.writeUTFBytes("GET " + urlParsed.urlpath + " HTTP/1.0\r\n");
      socket.writeUTFBytes("Host: " + urlParsed.host + ':' + urlParsed.port + "\r\n");
      socket.writeUTFBytes("Accept: multipart/x-mixed-replace\r\n");
      socket.writeUTFBytes("User-Agent: Locomote\r\n");
      socket.writeUTFBytes("\r\n");
    }

    private function onClose(e:Event):void {
      // Security error is thrown if this line is excluded
      socket.close();
    }

    private function onHttpHeaders(event:ProgressEvent):void {
      var parsed:* = request.readHeaders(socket, dataBuffer);
      if (false === parsed) {
        return;
      }

      if (200 !== parsed.code) {
        ErrorManager.dispatchError(parsed.code);
        disconnect();
        return;
      }

      if (!/^multipart\/x-mixed-replace/.test(parsed.headers['content-type'])) {
        ErrorManager.dispatchError(829);
        disconnect();
        return;
      }

      this.socket.removeEventListener(ProgressEvent.SOCKET_DATA, onHttpHeaders);
      this.socket.addEventListener(ProgressEvent.SOCKET_DATA, onImageData);

      if (0 < this.dataBuffer.bytesAvailable) {
        this.onImageData(event);
      }
    }

    private function onImageData(event:ProgressEvent):void {
      socket.readBytes(dataBuffer, dataBuffer.length);

      if (parseSubheaders) {
        var parsed:* = request.readHeaders(socket, dataBuffer);
        if (false === parsed) {
          return;
        }

        this.clen = parsed.headers['content-length'];
        parseSubheaders = false;
      }

      findImage();

      if (this.clen < this.dataBuffer.bytesAvailable) {
        onImageData(event);
      }
    };

    private function findImage():void {
      if (this.dataBuffer.bytesAvailable < this.clen + 2) {
        return;
      }

      image = new ByteArray()
      dataBuffer.readBytes(image, 0, clen + 2);

      var copy:ByteArray = new ByteArray();
      dataBuffer.readBytes(copy, 0);
      dataBuffer = copy;

      dispatchEvent(new Event("image"));
      clen = 0;
      parseSubheaders = true;
    }
  }
}

package com.axis.mjpegclient {

  import flash.events.ErrorEvent;
  import flash.events.Event;
  import flash.events.EventDispatcher;
  import flash.events.IOErrorEvent;
  import flash.events.ProgressEvent;
  import flash.events.SecurityErrorEvent;
  import flash.net.Socket;
  import flash.utils.ByteArray;

  import com.axis.Logger;
  import com.axis.ErrorManager;
  import com.axis.http.request;
  import com.axis.http.auth;

  [Event(name="image",type="flash.events.Event")]
  [Event(name="connect",type="flash.events.Event")]
  [Event(name="error",type="flash.events.Event")]

  public class Handle extends EventDispatcher {

    private var urlParsed:Object;
    private var socket:Socket = null;
    private var buffer:ByteArray = null;
    private var dataBuffer:ByteArray = null;
    private var url:String = "";
    private var params:Object;
    private var parseHeaders:Boolean = true;
    private var headers:Vector.<String> = new Vector.<String>();
    private var clen:int;
    private var parseSubheaders:Boolean = true;

    private var authState:String = "none";
    private var authOpts:Object = {};
    private var digestNC:uint = 1;
    private var method:String = "";

    public var image:ByteArray = null;

    public function Handle(urlParsed:Object) {
      this.urlParsed = urlParsed;
      this.buffer = new ByteArray();
      this.dataBuffer = new ByteArray();
      this.socket = new Socket();
      this.socket.timeout = 5000;
      this.socket.addEventListener(Event.CONNECT, onConnect);
      this.socket.addEventListener(Event.CLOSE, onClose);
      this.socket.addEventListener(ProgressEvent.SOCKET_DATA, onHttpHeaders);
      this.socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
      this.socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
    }

    private function onError(e:ErrorEvent):void {
      disconnect();
      dispatchEvent(new Event("IOError:" + e.errorID));
    }

    public function disconnect():void {
      if (!socket.connected) {
        return;
      }

      socket.close();
      image = null;
      buffer = null;
      dispatchEvent(new Event("disconnect"));
    }

    public function stop():void {
      disconnect();
    }

    public function connect():void {
      if (socket.connected) {
        disconnect();
      }

      Logger.log('MJPEGClient: connecting to', urlParsed.host + ':' + urlParsed.port);
      socket.connect(urlParsed.host, urlParsed.port);
    }

    private function onConnect(event:Event):void {
      buffer = new ByteArray();
      dataBuffer = new ByteArray();

      headers.length = 0;
      parseHeaders = true;
      parseSubheaders = true;

      var authHeader:String =
                    auth.authorizationHeader(method, authState, authOpts, urlParsed, digestNC++);

      socket.writeUTFBytes("GET " + urlParsed.urlpath + " HTTP/1.0\r\n");
      socket.writeUTFBytes("Host: " + urlParsed.host + ':' + urlParsed.port + "\r\n");
      socket.writeUTFBytes(authHeader);
      socket.writeUTFBytes("Accept: multipart/x-mixed-replace\r\n");
      socket.writeUTFBytes("User-Agent: Locomote\r\n");
      socket.writeUTFBytes("\r\n");
    }

    private function onClose(e:Event):void {
      // Security error is thrown if this line is excluded
      socket.close();
    }

    private function onHttpHeaders(event:ProgressEvent):void {
      var parsed:* = request.readHeaders(socket, dataBuffer);
      if (false === parsed) {
        return;
      }

      if (401 === parsed.code) {
        Logger.log('Unauthorized using auth method: ' + authState);
        /* Unauthorized, change authState and (possibly) try again */
        authOpts = parsed.headers['www-authenticate'];
        var newAuthState:String = auth.nextMethod(authState, authOpts);
        if (authState === newAuthState) {
          ErrorManager.dispatchError(parsed.code);
          return;
        }

        Logger.log('switching http-authorization from ' + authState + ' to ' + newAuthState);
        authState = newAuthState;
        connect();
        return;
      }

      if (200 !== parsed.code) {
        ErrorManager.dispatchError(parsed.code);
        disconnect();
        return;
      }

      if (!/^multipart\/x-mixed-replace/.test(parsed.headers['content-type'])) {
        ErrorManager.dispatchError(829);
        disconnect();
        return;
      }

      this.socket.removeEventListener(ProgressEvent.SOCKET_DATA, onHttpHeaders);
      this.socket.addEventListener(ProgressEvent.SOCKET_DATA, onImageData);

      if (0 < this.dataBuffer.bytesAvailable) {
        this.onImageData(event);
      }
    }

    private function onImageData(event:ProgressEvent):void {
      socket.readBytes(dataBuffer, dataBuffer.length);

      if (parseSubheaders) {
        var parsed:* = request.readHeaders(socket, dataBuffer);
        if (false === parsed) {
          return;
        }

        this.clen = parsed.headers['content-length'];
        parseSubheaders = false;
      }

      findImage();

      if (this.clen < this.dataBuffer.bytesAvailable) {
        onImageData(event);
      }
    };

    private function findImage():void {
      if (this.dataBuffer.bytesAvailable < this.clen + 2) {
        return;
      }

      image = new ByteArray()
      dataBuffer.readBytes(image, 0, clen + 2);

      var copy:ByteArray = new ByteArray();
      dataBuffer.readBytes(copy, 0);
      dataBuffer = copy;

      dispatchEvent(new Event("image"));
      clen = 0;
      parseSubheaders = true;
    }
  }
}

Add HTTP Auth support for MJPEG client

Add HTTP Auth support for MJPEG client


/*
	Weave (Web-based Analysis and Visualization Environment)
	Copyright (C) 2008-2011 University of Massachusetts Lowell

	This file is a part of Weave.

	Weave is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License, Version 3,
	as published by the Free Software Foundation.

	Weave is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Weave.  If not, see <http://www.gnu.org/licenses/>.
*/
package weave.ui
{
	import flash.events.Event;

	import mx.collections.IList;
	import mx.controls.Tree;
	import mx.core.ScrollPolicy;
	import mx.core.mx_internal;
	import mx.utils.ObjectUtil;

	import weave.utils.EventUtils;

	/**
	 * This class features a correctly behaving auto horizontal scroll policy.
	 * @author adufilie
	 */
	public class CustomTree extends Tree
	{
		public function CustomTree()
		{
			super();
			addEventListener("scroll", updateHScrollLater);
		}

		///////////////////////////////////////////////////////////////////////////////
		// solution for automatic maxHorizontalScrollPosition calculation
		// modified from http://www.frishy.com/2007/09/autoscrolling-for-flex-tree/

		// we need to override maxHorizontalScrollPosition because setting
		// Tree's maxHorizontalScrollPosition adds an indent value to it,
		// which we don't need as measureWidthOfItems seems to return exactly
		// what we need.  Not only that, but getIndent() seems to be broken
		// anyways (SDK-12578).

		// I hate using mx_internal stuff, but we can't do
		// super.super.maxHorizontalScrollPosition in AS 3, so we have to
		// emulate it.
		override public function get maxHorizontalScrollPosition():Number
		{
			if (isNaN(mx_internal::_maxHorizontalScrollPosition))
				return 0;

			return mx_internal::_maxHorizontalScrollPosition;
		}

		override public function set maxHorizontalScrollPosition(value:Number):void
		{
			if (ObjectUtil.numericCompare(mx_internal::_maxHorizontalScrollPosition, value) != 0)
			{
				mx_internal::_maxHorizontalScrollPosition = value;
				dispatchEvent(new Event("maxHorizontalScrollPositionChanged"));

				scrollAreaChanged = true;
				invalidateDisplayList();
			}
		}

		private const updateHScrollLater:Function = EventUtils.generateDelayedCallback(this, updateHScrollNow, 0);

		private function updateHScrollNow():void
		{
			// we call measureWidthOfItems to get the max width of the item renderers.
			// then we see how much space we need to scroll, setting maxHorizontalScrollPosition appropriately
			var widthOfVisibleItems:int = measureWidthOfItems(verticalScrollPosition - offscreenExtraRowsTop, listItems.length);
			var maxHSP:Number = widthOfVisibleItems - (unscaledWidth - viewMetrics.left - viewMetrics.right);

			var hspolicy:String = ScrollPolicy.ON;
			if (maxHSP <= 0)
			{
				maxHSP = 0;
				horizontalScrollPosition = 0;

				// horizontal scroll is kept on except when there is no vertical scroll
				// this avoids an infinite hide/show loop where hiding/showing the h-scroll bar affects the max h-scroll value
				if (maxVerticalScrollPosition == 0)
					hspolicy = ScrollPolicy.OFF;
			}

			maxHorizontalScrollPosition = maxHSP;

			if (horizontalScrollPolicy != hspolicy)
				horizontalScrollPolicy = hspolicy;
		}

		///////////////////////////////////////////////////////////////////////////////
		// solution for display bugs when hierarchical data changes

		private var _dataProvider:Object; // remembers previous value that was passed to "set dataProvider"

		override public function set dataProvider(value:Object):void
		{
			_dataProvider = value;
			super.dataProvider = value;
		}

		/**
		 * This function must be called whenever the hierarchical data changes.
		 * Otherwise, the Tree will not display properly.
		 */
		public function refreshDataProvider():void
		{
			var _firstVisibleItem:Object = firstVisibleItem;
			var _selectedItems:Array = selectedItems;
			var _openItems:Array = openItems.concat();

			// use value previously passed to "set dataProvider" in order to create a new collection wrapper.
			dataProvider = _dataProvider;
			// commitProperties() behaves as desired when both dataProvider and openItems are set.
			openItems = _openItems;

			validateNow(); // necessary in order to select previous items and scroll back to the correct position

			// scroll to the previous item, but only if it is within scroll range
			var vsp:int = getItemIndex(_firstVisibleItem);
			if (vsp >= 0 && vsp <= maxVerticalScrollPosition)
				firstVisibleItem = _firstVisibleItem;

			// selectedItems must be set last to avoid a bug where the Tree scrolls to the top.
			selectedItems = _selectedItems;
		}

		/**
		 * This contains a workaround for a problem in List.configureScrollBars relying on a non-working function CursorBookmark.getViewIndex().
		 * This fixes the bug where the tree would scroll all the way from the bottom to the top when a node is collapsed.
		 */
		override protected function configureScrollBars():void
		{
			var rda:Boolean = runningDataEffect;

			runningDataEffect = true;

			// This is not a perfect scrolling solution.  It looks ok when there is a partial row showing at the bottom.
			var mvsp:int = Math.max(0, collection.length - listItems.length + 1);
			if (verticalScrollPosition > mvsp)
				verticalScrollPosition = mvsp;

			super.configureScrollBars();

			runningDataEffect = rda;
		}

		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			updateHScrollLater();

			// If showRoot is false and root is showing, force commitProperties() to fix the problem.
			// This workaround requires that the data descriptor reports that the root item is a branch and it has children, even if it doesn't.
			if (!showRoot)
			{
				var rootItem:Object = dataProvider is IList && (dataProvider as IList).length > 0 ? (dataProvider as IList).getItemAt(0) : null;
				if (rootItem && itemToItemRenderer(rootItem))
				{
					mx_internal::showRootChanged = true;
					commitProperties();
				}
			}

			// "iterator" is a HierarchicalViewCursor, and its movePrevious()/moveNext()/seek() functions do not work if "current" is null.
			// Calling refreshDataProvider() returns the tree to a working state.
			if (iterator && iterator.current == null)
				refreshDataProvider();

			super.updateDisplayList(unscaledWidth, unscaledHeight);
		}
	}
}

/*
	Weave (Web-based Analysis and Visualization Environment)
	Copyright (C) 2008-2011 University of Massachusetts Lowell

	This file is a part of Weave.

	Weave is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License, Version 3,
	as published by the Free Software Foundation.

	Weave is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Weave.  If not, see <http://www.gnu.org/licenses/>.
*/
package weave.ui
{
	import flash.events.Event;

	import mx.collections.ICollectionView;
	import mx.collections.IList;
	import mx.collections.IViewCursor;
	import mx.controls.Tree;
	import mx.core.ScrollPolicy;
	import mx.core.mx_internal;
	import mx.utils.ObjectUtil;

	import weave.utils.EventUtils;

	/**
	 * This class features a correctly behaving auto horizontal scroll policy.
	 * @author adufilie
	 */
	public class CustomTree extends Tree
	{
		public function CustomTree()
		{
			super();
			addEventListener("scroll", updateHScrollLater);
		}

		///////////////////////////////////////////////////////////////////////////////
		// solution for automatic maxHorizontalScrollPosition calculation
		// modified from http://www.frishy.com/2007/09/autoscrolling-for-flex-tree/

		// we need to override maxHorizontalScrollPosition because setting
		// Tree's maxHorizontalScrollPosition adds an indent value to it,
		// which we don't need as measureWidthOfItems seems to return exactly
		// what we need.  Not only that, but getIndent() seems to be broken
		// anyways (SDK-12578).

		// I hate using mx_internal stuff, but we can't do
		// super.super.maxHorizontalScrollPosition in AS 3, so we have to
		// emulate it.
		override public function get maxHorizontalScrollPosition():Number
		{
			if (isNaN(mx_internal::_maxHorizontalScrollPosition))
				return 0;

			return mx_internal::_maxHorizontalScrollPosition;
		}

		override public function set maxHorizontalScrollPosition(value:Number):void
		{
			if (ObjectUtil.numericCompare(mx_internal::_maxHorizontalScrollPosition, value) != 0)
			{
				mx_internal::_maxHorizontalScrollPosition = value;
				dispatchEvent(new Event("maxHorizontalScrollPositionChanged"));

				scrollAreaChanged = true;
				invalidateDisplayList();
			}
		}

		private const updateHScrollLater:Function = EventUtils.generateDelayedCallback(this, updateHScrollNow, 0);

		private function updateHScrollNow():void
		{
			// we call measureWidthOfItems to get the max width of the item renderers.
			// then we see how much space we need to scroll, setting maxHorizontalScrollPosition appropriately
			var widthOfVisibleItems:int = measureWidthOfItems(verticalScrollPosition - offscreenExtraRowsTop, listItems.length);
			var maxHSP:Number = widthOfVisibleItems - (unscaledWidth - viewMetrics.left - viewMetrics.right);

			var hspolicy:String = ScrollPolicy.ON;
			if (maxHSP <= 0)
			{
				maxHSP = 0;
				horizontalScrollPosition = 0;

				// horizontal scroll is kept on except when there is no vertical scroll
				// this avoids an infinite hide/show loop where hiding/showing the h-scroll bar affects the max h-scroll value
				if (maxVerticalScrollPosition == 0)
					hspolicy = ScrollPolicy.OFF;
			}

			maxHorizontalScrollPosition = maxHSP;

			if (horizontalScrollPolicy != hspolicy)
				horizontalScrollPolicy = hspolicy;
		}

		///////////////////////////////////////////////////////////////////////////////
		// solution for display bugs when hierarchical data changes

		private var _dataProvider:Object; // remembers previous value that was passed to "set dataProvider"

		override public function set dataProvider(value:Object):void
		{
			_dataProvider = value;
			super.dataProvider = value;
		}

		/**
		 * This function must be called whenever the hierarchical data changes.
		 * Otherwise, the Tree will not display properly.
		 */
		public function refreshDataProvider():void
		{
			var _firstVisibleItem:Object = firstVisibleItem;
			var _selectedItems:Array = selectedItems;
			var _openItems:Array = openItems.concat();

			// use value previously passed to "set dataProvider" in order to create a new collection wrapper.
			dataProvider = _dataProvider;
			// commitProperties() behaves as desired when both dataProvider and openItems are set.
			openItems = _openItems;

			validateNow(); // necessary in order to select previous items and scroll back to the correct position

			// scroll to the previous item, but only if it is within scroll range
			var vsp:int = getItemIndex(_firstVisibleItem);
			if (vsp >= 0 && vsp <= maxVerticalScrollPosition)
				firstVisibleItem = _firstVisibleItem;

			// selectedItems must be set last to avoid a bug where the Tree scrolls to the top.
			selectedItems = _selectedItems;
		}

		/**
		 * This contains a workaround for a problem in List.configureScrollBars relying on a non-working function CursorBookmark.getViewIndex().
		 * This fixes the bug where the tree would scroll all the way from the bottom to the top when a node is collapsed.
		 */
		override protected function configureScrollBars():void
		{
			var ac:ICollectionView = actualCollection;
			var ai:IViewCursor = actualIterator;
			var rda:Boolean = runningDataEffect;

			runningDataEffect = true;
			actualCollection = ac || collection; // avoids null pointer error
			actualIterator = ai || iterator;

			// This is not a perfect scrolling solution.  It looks ok when there is a partial row showing at the bottom.
			var mvsp:int = Math.max(0, collection.length - listItems.length + 1);
			if (verticalScrollPosition > mvsp)
				verticalScrollPosition = mvsp;

			super.configureScrollBars();

			runningDataEffect = rda;
			actualCollection = ac;
			actualIterator = ai;
		}

		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			updateHScrollLater();

			// If showRoot is false and root is showing, force commitProperties() to fix the problem.
			// This workaround requires that the data descriptor reports that the root item is a branch and it has children, even if it doesn't.
			if (!showRoot)
			{
				var rootItem:Object = dataProvider is IList && (dataProvider as IList).length > 0 ? (dataProvider as IList).getItemAt(0) : null;
				if (rootItem && itemToItemRenderer(rootItem))
				{
					mx_internal::showRootChanged = true;
					commitProperties();
				}
			}

			// "iterator" is a HierarchicalViewCursor, and its movePrevious()/moveNext()/seek() functions do not work if "current" is null.
			// Calling refreshDataProvider() returns the tree to a working state.
			if (iterator && iterator.current == null)
				refreshDataProvider();

			super.updateDisplayList(unscaledWidth, unscaledHeight);
		}
	}
}

work around null pointer error

work around null pointer error


/**
* jQuery AS3 Webcam
*
* Copyright (c) 2012, Sergey Shilko (sergey.shilko@gmail.com)
*
* Date: 08/01/2012
*
* @author Sergey Shilko
* @version 1.0
*
**/

/* SWF external interface:
 * webcam.save() - get base64 encoded JPEG image
 * webcam.getCameraList() - get list of available cams
 * webcam.setCamera(i) - set camera, camera index retrieved with getCameraList
 * */

/* External triggers on events:
 * webcam.isClientReady() - you respond to SWF with true (by default) meaning javascript is ready to accept callbacks
 * webcam.cameraConnected() - camera connected callback from SWF
 * webcam.noCameraFound() - SWF response that it cannot find any suitable camera
 * webcam.cameraEnabled() - SWF response when camera tracking is enabled (this is called multiple times, use isCameraEnabled flag)
 * webcam.cameraDisabled()- SWF response, user denied usage of camera
 * webcam.swfApiFail()    - Javascript failed to make call to SWF
 * webcam.debug()         - debug callback used from SWF and can be used from javascript side too
 * */

package {

    import flash.system.Security;
    import flash.system.SecurityPanel;

    import flash.external.ExternalInterface;

    import flash.display.Sprite;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.display.BitmapData;
    import flash.events.*;
    import flash.utils.ByteArray;
    import flash.utils.Timer;

    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display.StageQuality;

    import com.adobe.images.JPGEncoder;
    import Base64;

    public class sAS3Cam extends Sprite {

	private var camera:Camera  = null;
        private var video:Video    = null;
        private var bmd:BitmapData = null;

        private var camBandwidth:int = 0; // Specifies the maximum amount of bandwidth that the current outgoing video feed can use, in bytes per second. To specify that Flash Player video can use as much bandwidth as needed to maintain the value of quality , pass 0 for bandwidth . The default value is 16384.
        private var camQuality:int = 100; // this value is 0-100 with 1 being the lowest quality. Pass 0 if you want the quality to vary to keep better framerates
        private var camFrameRate:int = 24;

        private var camResolution:Array;

        private function getCameraResolution():Array {
            var resolutionWidth:Number = this.loaderInfo.parameters["resolutionWidth"];
            var videoWidth:Number      = Math.floor(resolutionWidth);

            var resolutionHeight:Number = this.loaderInfo.parameters["resolutionHeight"];
            var videoHeight:Number      = Math.floor(resolutionHeight);

            var serverWidth:Number  = Math.floor(stage.stageWidth);
            var serverHeight:Number = Math.floor(stage.stageHeight);

            var result:Array = [Math.max(videoWidth, serverWidth), Math.max(videoHeight, serverHeight)];
            return result;
        }

        private function setupCamera(useCamera:Camera):void {
            useCamera.setMode(camResolution[0],
                              camResolution[1],
                              camFrameRate);

            useCamera.setQuality(camBandwidth, camQuality);
            useCamera.addEventListener(StatusEvent.STATUS, statusHandler);
            useCamera.setMotionLevel(100); //disable motion detection
        }

        private function setVideoCamera(useCamera:Camera):void {
            var doSmoothing:Boolean = this.loaderInfo.parameters["smoothing"];
            var doDeblocking:Number = this.loaderInfo.parameters["deblocking"];

            video = new Video();
            video.smoothing  = doSmoothing;
            video.deblocking = doDeblocking;
            video.attachCamera(useCamera);
            addChild(video);
        }

	public function sAS3Cam():void {
            flash.system.Security.allowDomain("*");
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.quality = StageQuality.BEST;
            stage.align = StageAlign.TOP_LEFT;

            camera = Camera.getCamera();

            if (null != camera) {
                if (ExternalInterface.available) {
                    camResolution = getCameraResolution();
                    setupCamera(camera);
                    setVideoCamera(camera);

                    bmd = new BitmapData(stage.width, stage.height);

                    try {
                        var containerReady:Boolean = isContainerReady();
                        if (containerReady) {
                            setupCallbacks();
                        }  else {
                            var readyTimer:Timer = new Timer(100);
                            readyTimer.addEventListener(TimerEvent.TIMER, timerHandler);
                            readyTimer.start();
                        }
                    } catch (err:Error) { } finally { }
                } else {

                }

            } else {
                extCall('noCameraFound');
            }
	}

        private function statusHandler(event:StatusEvent):void {
            if (event.code == "Camera.Unmuted") {
                camera.removeEventListener(StatusEvent.STATUS, statusHandler);
                extCall('cameraEnabled');
            } else {
                extCall('cameraDisabled');
            }
        }

        private function extCall(func:String):Boolean {
            var target:String = this.loaderInfo.parameters["callTarget"];
            return ExternalInterface.call(target + "." + func);
        }

        private function isContainerReady():Boolean {
            var result:Boolean = extCall("isClientReady");
            return result;
        }

        private function setupCallbacks():void {
            ExternalInterface.addCallback("save", save);
            ExternalInterface.addCallback("setCamera", setCamera);
            ExternalInterface.addCallback("getCameraList", getCameraList);
            extCall('cameraConnected');
            /* when we have pernament accept policy --> */
            if (!camera.muted) {
                extCall('cameraEnabled');
            } else {
                Security.showSettings(SecurityPanel.PRIVACY);
            }
            /* when we have pernament accept policy <-- */
        }

        private function timerHandler(event:TimerEvent):void {
            var isReady:Boolean = isContainerReady();
            if (isReady) {
                Timer(event.target).stop();
                setupCallbacks();
            }
        }

	public function getCameraList():Array {
            var list:Array = Camera.names;
            list.reverse();
            return list;
	}

	public function setCamera(id:Number):Boolean {
            var newcam:Camera = Camera.getCamera(id.toString());
            if (newcam) {
                camera = newcam;
                setupCamera(camera);
                setVideoCamera(camera);
                return true;
            }
            return false;
	}

        public function save():String {
            bmd.draw(video);
            video.attachCamera(null); //this stops video stream, video will pause on last frame (like a preview)
            var quality:Number = 100;
            var byteArray:ByteArray = new JPGEncoder(quality).encode(bmd);
            var string:String = Base64.encodeByteArray(byteArray);
            return string;
        }

    }

}

/**
* jQuery AS3 Webcam
*
* Copyright (c) 2012, Sergey Shilko (sergey.shilko@gmail.com)
*
* Date: 08/01/2012
*
* @author Sergey Shilko
* @version 1.0
*
**/

/* SWF external interface:
 * webcam.save() - get base64 encoded JPEG image
 * webcam.getCameraList() - get list of available cams
 * webcam.setCamera(i) - set camera, camera index retrieved with getCameraList
 * */

/* External triggers on events:
 * webcam.isClientReady() - you respond to SWF with true (by default) meaning javascript is ready to accept callbacks
 * webcam.cameraConnected() - camera connected callback from SWF
 * webcam.noCameraFound() - SWF response that it cannot find any suitable camera
 * webcam.cameraEnabled() - SWF response when camera tracking is enabled (this is called multiple times, use isCameraEnabled flag)
 * webcam.cameraDisabled()- SWF response, user denied usage of camera
 * webcam.swfApiFail()    - Javascript failed to make call to SWF
 * webcam.debug()         - debug callback used from SWF and can be used from javascript side too
 * */

package {

    import flash.system.Security;
    import flash.system.SecurityPanel;

    import flash.external.ExternalInterface;

    import flash.display.Sprite;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.display.BitmapData;
    import flash.events.*;
    import flash.utils.ByteArray;
    import flash.utils.Timer;

    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display.StageQuality;

    import com.adobe.images.JPGEncoder;
    import Base64;

    public class sAS3Cam extends Sprite {

	private var camera:Camera  = null;
        private var video:Video    = null;
        private var bmd:BitmapData = null;

        private var camBandwidth:int = 0; // Specifies the maximum amount of bandwidth that the current outgoing video feed can use, in bytes per second. To specify that Flash Player video can use as much bandwidth as needed to maintain the value of quality , pass 0 for bandwidth . The default value is 16384.
        private var camQuality:int = 100; // this value is 0-100 with 1 being the lowest quality. Pass 0 if you want the quality to vary to keep better framerates
        private var camFrameRate:int = 24;

        private var camResolution:Array;

        private function getCameraResolution():Array {
            var resolutionWidth:Number = this.loaderInfo.parameters["resolutionWidth"];
            var videoWidth:Number      = Math.floor(resolutionWidth);

            var resolutionHeight:Number = this.loaderInfo.parameters["resolutionHeight"];
            var videoHeight:Number      = Math.floor(resolutionHeight);

            var serverWidth:Number  = Math.floor(stage.stageWidth);
            var serverHeight:Number = Math.floor(stage.stageHeight);

            var result:Array = [Math.max(videoWidth, serverWidth), Math.max(videoHeight, serverHeight)];
            return result;
        }

        private function setupCamera(useCamera:Camera):void {
            useCamera.setMode(camResolution[0],
                              camResolution[1],
                              camFrameRate);

            useCamera.setQuality(camBandwidth, camQuality);
            useCamera.addEventListener(StatusEvent.STATUS, statusHandler);
            useCamera.setMotionLevel(100); //disable motion detection
        }

        private function setVideoCamera(useCamera:Camera):void {
            var doSmoothing:Boolean = this.loaderInfo.parameters["smoothing"];
            var doDeblocking:Number = this.loaderInfo.parameters["deblocking"];

            video = new Video(camResolution[0],camResolution[1]);
            video.smoothing  = doSmoothing;
            video.deblocking = doDeblocking;
            video.attachCamera(useCamera);
            addChild(video);
        }

	public function sAS3Cam():void {
            flash.system.Security.allowDomain("*");
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.quality = StageQuality.BEST;
            stage.align = StageAlign.TOP_LEFT;

            camera = Camera.getCamera();

            if (null != camera) {
                if (ExternalInterface.available) {
                    camResolution = getCameraResolution();
                    setupCamera(camera);
                    setVideoCamera(camera);

                    bmd = new BitmapData(stage.width, stage.height);

                    try {
                        var containerReady:Boolean = isContainerReady();
                        if (containerReady) {
                            setupCallbacks();
                        }  else {
                            var readyTimer:Timer = new Timer(100);
                            readyTimer.addEventListener(TimerEvent.TIMER, timerHandler);
                            readyTimer.start();
                        }
                    } catch (err:Error) { } finally { }
                } else {

                }

            } else {
                extCall('noCameraFound');
            }
	}

        private function statusHandler(event:StatusEvent):void {
            if (event.code == "Camera.Unmuted") {
                camera.removeEventListener(StatusEvent.STATUS, statusHandler);
                extCall('cameraEnabled');
            } else {
                extCall('cameraDisabled');
            }
        }

        private function extCall(func:String):Boolean {
            var target:String = this.loaderInfo.parameters["callTarget"];
            return ExternalInterface.call(target + "." + func);
        }

        private function isContainerReady():Boolean {
            var result:Boolean = extCall("isClientReady");
            return result;
        }

        private function setupCallbacks():void {
            ExternalInterface.addCallback("save", save);
            ExternalInterface.addCallback("setCamera", setCamera);
            ExternalInterface.addCallback("getCameraList", getCameraList);
            extCall('cameraConnected');
            /* when we have pernament accept policy --> */
            if (!camera.muted) {
                extCall('cameraEnabled');
            } else {
                Security.showSettings(SecurityPanel.PRIVACY);
            }
            /* when we have pernament accept policy <-- */
        }

        private function timerHandler(event:TimerEvent):void {
            var isReady:Boolean = isContainerReady();
            if (isReady) {
                Timer(event.target).stop();
                setupCallbacks();
            }
        }

	public function getCameraList():Array {
            var list:Array = Camera.names;
            list.reverse();
            return list;
	}

	public function setCamera(id:Number):Boolean {
            var newcam:Camera = Camera.getCamera(id.toString());
            if (newcam) {
                camera = newcam;
                setupCamera(camera);
                setVideoCamera(camera);
                return true;
            }
            return false;
	}

        public function save():String {
            bmd.draw(video);
            video.attachCamera(null); //this stops video stream, video will pause on last frame (like a preview)
            var quality:Number = 100;
            var byteArray:ByteArray = new JPGEncoder(quality).encode(bmd);
            var string:String = Base64.encodeByteArray(byteArray);
            return string;
        }

    }

}

Add height and width to Video ctor

Add height and width to Video ctor


package aerys.minko.scene.node
{
	import aerys.minko.render.Effect;
	import aerys.minko.render.geometry.Geometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.render.material.basic.BasicShader;
	import aerys.minko.scene.controller.AbstractController;
	import aerys.minko.scene.controller.mesh.MeshVisibilityController;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.bounding.FrustumCulling;
	import aerys.minko.type.enum.DataProviderUsage;
	import aerys.minko.type.math.Ray;

	/**
	 * Mesh objects are a visible instance of a Geometry rendered using a specific
	 * Effect with specific rendering properties.
	 *
	 *

	 * Those rendering properties are stored in a DataBindings object so they can
	 * be directly used by the shaders in the rendering API.
	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Mesh extends AbstractSceneNode
	{
		public static const DEFAULT_MATERIAL	: Effect	= new Effect(
			new BasicShader()
		);

		private var _geometry			: Geometry					= null;
		private var _properties			: DataProvider				= null;
		private var _material			: Material					= null;
		private var _bindings			: DataBindings				= null;

		private var _visibility			: MeshVisibilityController	= new MeshVisibilityController();

		private var _frame				: uint						= 0;

		private var _cloned				: Signal 					= new Signal('Mesh.clones');
		private var _materialChanged	: Signal					= new Signal('Mesh.materialChanged');
		private var _frameChanged		: Signal					= new Signal('Mesh.frameChanged');
		private var _geometryChanged	: Signal					= new Signal('Mesh.geometryChanged');

		/**
		 * A DataProvider object already bound to the Mesh bindings.
		 *
		 *

		 * // set the "diffuseColor" property to 0x0000ffff
		 * mesh.properties.diffuseColor = 0x0000ffff;
		 *
		 * // animate the "diffuseColor" property
		 * mesh.addController(
		 *   new AnimationController(
		 * 	  new <ITimeline>[new ColorTimeline(
		 * 	    "dataProvider.diffuseColor",
		 * 	    5000,
		 * 	    new <uint>[0xffffffff, 0xffffff00, 0xffffffff]
		 *    )]
		 *   )
		 * );
		 *

		 *
		 * @return
		 *
		 */
		public function get properties() : DataProvider
		{
			return _properties;
		}

		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get material() : Material
		{
			return _material;
		}
		public function set material(value : Material) : void
		{
			if (_material != value)
			{
				if (_material)
					_bindings.removeProvider(_material);

				_material = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		/**
		 * The rendering properties provided to the shaders to customize
		 * how the mesh will appear on screen.
		 *
		 * @return
		 *
		 */
		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The Geometry of the mesh.
		 * @return
		 *
		 */
		public function get geometry() : Geometry
		{
			return _geometry;
		}

		public function set geometry(value : Geometry) : void
		{
			if (_geometry != value)
			{
				var oldGeometry	: Geometry = _geometry;

				_geometry = value;
				_geometryChanged.execute(this, oldGeometry, value);
			}
		}

		/**
		 * Whether the mesh is visible or not.
		 *
		 * @return
		 *
		 */
		public function get visible() : Boolean
		{
			return _visibility.visible;
		}
		public function set visible(value : Boolean) : void
		{
			_visibility.visible = value;
		}

		public function get frustumCulling() : uint
		{
			return _visibility.frustumCulling;
		}
		public function set frustumCulling(value : uint) : void
		{
			_visibility.frustumCulling = value;
		}

		public function get cloned() : Signal
		{
			return _cloned;
		}

		public function get materialChanged() : Signal
		{
			return _materialChanged;
		}

		public function get frameChanged() : Signal
		{
			return _frameChanged;
		}

		public function get geometryChanged() : Signal
		{
			return _geometryChanged;
		}

		public function get frame() : uint
		{
			return _frame;
		}
		public function set frame(value : uint) : void
		{
			if (_frame != value)
			{
				var oldFrame : uint = _frame;

				_frame = value;
				_frameChanged.execute(this, oldFrame, value);
			}
		}

		public function Mesh(geometry	: Geometry	= null,
							 material	: Material	= null,
							 ...controllers)
		{
			super();

			initialize(geometry, material, controllers);
		}

		private function initialize(geometry	: Geometry,
									material	: Material,
									controllers	: Array) : void
		{
			_bindings = new DataBindings(this);
			this.properties = new DataProvider(properties, 'meshProperties', DataProviderUsage.EXCLUSIVE);

			_geometry = geometry;
			this.material = material || new BasicMaterial();

//			_visibility.frustumCulling = FrustumCulling.ENABLED;
			addController(_visibility);

			while (controllers && !(controllers[0] is AbstractController))
				controllers = controllers[0];

			if (controllers)
				for each (var ctrl : AbstractController in controllers)
					addController(ctrl);
		}

		public function cast(ray : Ray, maxDistance : Number = Number.POSITIVE_INFINITY) : Number
		{
			return _geometry.boundingBox.testRay(
				ray,
				worldToLocal,
				maxDistance
			);
		}

		override public function clone(cloneControllers : Boolean = false) : ISceneNode
		{
			var clone : Mesh = new Mesh();

			clone.copyFrom(this, true, cloneControllers);

			return clone;
		}

		override protected function addedToSceneHandler(child : ISceneNode, scene : Scene) : void
		{
			super.addedToSceneHandler(child, scene);

			if (child === this)
				_bindings.addProvider(transformData);
		}

		override protected function removedFromSceneHandler(child : ISceneNode, scene : Scene) : void
		{
			super.removedFromSceneHandler(child, scene);

			if (child === this)
				_bindings.removeProvider(transformData);
		}

		protected function copyFrom(source 				: Mesh,
									withBindings 		: Boolean,
									cloneControllers 	: Boolean) : void
		{
			var numControllers : uint = source.numControllers;

			name 		= source.name;

			geometry 	= source._geometry;
			properties	= DataProvider(source._properties.clone());

			_bindings.copySharedProvidersFrom(source._bindings);

			copyControllersFrom(
				source, this, cloneControllers, new <AbstractController>[source._visibility]
			);

			_visibility = source._visibility.clone() as MeshVisibilityController;
			addController(_visibility);

			transform.copyFrom(source.transform);
			material = source._material;

			source.cloned.execute(this, source);
		}
	}
}

package aerys.minko.scene.node
{
	import aerys.minko.render.Effect;
	import aerys.minko.render.geometry.Geometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.render.material.basic.BasicShader;
	import aerys.minko.scene.controller.AbstractController;
	import aerys.minko.scene.controller.mesh.MeshVisibilityController;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.bounding.FrustumCulling;
	import aerys.minko.type.enum.DataProviderUsage;
	import aerys.minko.type.math.Ray;

	/**
	 * Mesh objects are a visible instance of a Geometry rendered using a specific
	 * Effect with specific rendering properties.
	 *
	 *

	 * Those rendering properties are stored in a DataBindings object so they can
	 * be directly used by the shaders in the rendering API.
	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Mesh extends AbstractSceneNode
	{
		public static const DEFAULT_MATERIAL	: Material	= new Material(
			new Effect(new BasicShader())
		);

		private var _geometry			: Geometry					= null;
		private var _properties			: DataProvider				= null;
		private var _material			: Material					= null;
		private var _bindings			: DataBindings				= null;

		private var _visibility			: MeshVisibilityController	= new MeshVisibilityController();

		private var _frame				: uint						= 0;

		private var _cloned				: Signal 					= new Signal('Mesh.clones');
		private var _materialChanged	: Signal					= new Signal('Mesh.materialChanged');
		private var _frameChanged		: Signal					= new Signal('Mesh.frameChanged');
		private var _geometryChanged	: Signal					= new Signal('Mesh.geometryChanged');

		/**
		 * A DataProvider object already bound to the Mesh bindings.
		 *
		 *

		 * // set the "diffuseColor" property to 0x0000ffff
		 * mesh.properties.diffuseColor = 0x0000ffff;
		 *
		 * // animate the "diffuseColor" property
		 * mesh.addController(
		 *   new AnimationController(
		 * 	  new <ITimeline>[new ColorTimeline(
		 * 	    "dataProvider.diffuseColor",
		 * 	    5000,
		 * 	    new <uint>[0xffffffff, 0xffffff00, 0xffffffff]
		 *    )]
		 *   )
		 * );
		 *

		 *
		 * @return
		 *
		 */
		public function get properties() : DataProvider
		{
			return _properties;
		}

		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get material() : Material
		{
			return _material;
		}
		public function set material(value : Material) : void
		{
			if (_material != value)
			{
				if (_material)
					_bindings.removeProvider(_material);

				_material = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		/**
		 * The rendering properties provided to the shaders to customize
		 * how the mesh will appear on screen.
		 *
		 * @return
		 *
		 */
		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The Geometry of the mesh.
		 * @return
		 *
		 */
		public function get geometry() : Geometry
		{
			return _geometry;
		}

		public function set geometry(value : Geometry) : void
		{
			if (_geometry != value)
			{
				var oldGeometry	: Geometry = _geometry;

				_geometry = value;
				_geometryChanged.execute(this, oldGeometry, value);
			}
		}

		/**
		 * Whether the mesh is visible or not.
		 *
		 * @return
		 *
		 */
		public function get visible() : Boolean
		{
			return _visibility.visible;
		}
		public function set visible(value : Boolean) : void
		{
			_visibility.visible = value;
		}

		public function get frustumCulling() : uint
		{
			return _visibility.frustumCulling;
		}
		public function set frustumCulling(value : uint) : void
		{
			_visibility.frustumCulling = value;
		}

		public function get cloned() : Signal
		{
			return _cloned;
		}

		public function get materialChanged() : Signal
		{
			return _materialChanged;
		}

		public function get frameChanged() : Signal
		{
			return _frameChanged;
		}

		public function get geometryChanged() : Signal
		{
			return _geometryChanged;
		}

		public function get frame() : uint
		{
			return _frame;
		}
		public function set frame(value : uint) : void
		{
			if (_frame != value)
			{
				var oldFrame : uint = _frame;

				_frame = value;
				_frameChanged.execute(this, oldFrame, value);
			}
		}

		public function Mesh(geometry	: Geometry	= null,
							 material	: Material	= null,
							 ...controllers)
		{
			super();

			initialize(geometry, material, controllers);
		}

		private function initialize(geometry	: Geometry,
									material	: Material,
									controllers	: Array) : void
		{
			_bindings = new DataBindings(this);
			this.properties = new DataProvider(properties, 'meshProperties', DataProviderUsage.EXCLUSIVE);

			_geometry = geometry;
			this.material = material || DEFAULT_MATERIAL;

//			_visibility.frustumCulling = FrustumCulling.ENABLED;
			addController(_visibility);

			while (controllers && !(controllers[0] is AbstractController))
				controllers = controllers[0];

			if (controllers)
				for each (var ctrl : AbstractController in controllers)
					addController(ctrl);
		}

		public function cast(ray : Ray, maxDistance : Number = Number.POSITIVE_INFINITY) : Number
		{
			return _geometry.boundingBox.testRay(
				ray,
				worldToLocal,
				maxDistance
			);
		}

		override public function clone(cloneControllers : Boolean = false) : ISceneNode
		{
			var clone : Mesh = new Mesh();

			clone.copyFrom(this, true, cloneControllers);

			return clone;
		}

		override protected function addedToSceneHandler(child : ISceneNode, scene : Scene) : void
		{
			super.addedToSceneHandler(child, scene);

			if (child === this)
				_bindings.addProvider(transformData);
		}

		override protected function removedFromSceneHandler(child : ISceneNode, scene : Scene) : void
		{
			super.removedFromSceneHandler(child, scene);

			if (child === this)
				_bindings.removeProvider(transformData);
		}

		protected function copyFrom(source 				: Mesh,
									withBindings 		: Boolean,
									cloneControllers 	: Boolean) : void
		{
			var numControllers : uint = source.numControllers;

			name 		= source.name;

			geometry 	= source._geometry;
			properties	= DataProvider(source._properties.clone());

			_bindings.copySharedProvidersFrom(source._bindings);

			copyControllersFrom(
				source, this, cloneControllers, new <AbstractController>[source._visibility]
			);

			_visibility = source._visibility.clone() as MeshVisibilityController;
			addController(_visibility);

			transform.copyFrom(source.transform);
			material = source._material;

			source.cloned.execute(this, source);
		}
	}
}

fix Mesh.DEFAULT_MATERIAL to be an actual Material object


package dolly {
import dolly.core.dolly_internal;
import dolly.data.CompositeCloneableClass;

import mx.collections.ArrayCollection;
import mx.collections.ArrayList;

import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;
import org.flexunit.asserts.assertEquals;
import org.flexunit.asserts.assertFalse;
import org.flexunit.asserts.assertNotNull;
import org.hamcrest.assertThat;
import org.hamcrest.collection.array;
import org.hamcrest.collection.arrayWithSize;
import org.hamcrest.collection.everyItem;
import org.hamcrest.core.isA;
import org.hamcrest.object.equalTo;

use namespace dolly_internal;

public class CloningOfCompositeCloneableClassTest {

	private var compositeCloneableClass:CompositeCloneableClass;
	private var compositeCloneableClassType:Type;

	[Before]
	public function before():void {
		compositeCloneableClass = new CompositeCloneableClass();
		compositeCloneableClass.array = [1, 2, 3, 4, 5];
		compositeCloneableClass.arrayList = new ArrayList([1, 2, 3, 4, 5]);
		compositeCloneableClass.arrayCollection = new ArrayCollection([1, 2, 3, 4, 5]);

		compositeCloneableClassType = Type.forInstance(compositeCloneableClass);
	}

	[After]
	public function after():void {
		compositeCloneableClass = null;
		compositeCloneableClassType = null;
	}

	[Test]
	public function findingAllWritableFieldsForType():void {
		const writableFields:Vector.<Field> = Cloner.findAllWritableFieldsForType(compositeCloneableClassType);
		assertNotNull(writableFields);
		assertEquals(4, writableFields.length);
	}

	[Test]
	public function cloningOfArray():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		assertNotNull(clone.array);
		assertThat(clone.array, arrayWithSize(5));
		assertThat(clone.array, compositeCloneableClass.array);
		assertFalse(clone.array == compositeCloneableClass.array);
		assertThat(clone.array, everyItem(isA(Number)));
		assertThat(clone.array, array(equalTo(1), equalTo(2), equalTo(3), equalTo(4), equalTo(5)));
	}

	[Test]
	public function cloningOfArrayList():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		const arrayList:ArrayList = clone.arrayList;

		assertNotNull(arrayList);
		assertFalse(clone.arrayList == compositeCloneableClass.arrayList);
		assertEquals(arrayList.length, 5);
		assertEquals(arrayList.getItemAt(0), 1);
		assertEquals(arrayList.getItemAt(1), 2);
		assertEquals(arrayList.getItemAt(2), 3);
		assertEquals(arrayList.getItemAt(3), 4);
		assertEquals(arrayList.getItemAt(4), 5);
	}

	[Test]
	public function cloningOfArrayCollection():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		const targetArrayCollection:ArrayCollection = clone.arrayCollection;

		assertNotNull(targetArrayCollection);
		assertFalse(clone.arrayList == compositeCloneableClass.arrayList);
		assertEquals(targetArrayCollection.length, 5);
		assertEquals(targetArrayCollection.getItemAt(0), 1);
		assertEquals(targetArrayCollection.getItemAt(1), 2);
		assertEquals(targetArrayCollection.getItemAt(2), 3);
		assertEquals(targetArrayCollection.getItemAt(3), 4);
		assertEquals(targetArrayCollection.getItemAt(4), 5);
	}
}
}

package dolly {
import dolly.core.dolly_internal;
import dolly.data.CompositeCloneableClass;

import mx.collections.ArrayCollection;
import mx.collections.ArrayList;

import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;
import org.flexunit.asserts.assertEquals;
import org.flexunit.asserts.assertFalse;
import org.flexunit.asserts.assertNotNull;
import org.hamcrest.assertThat;
import org.hamcrest.collection.array;
import org.hamcrest.collection.arrayWithSize;
import org.hamcrest.collection.everyItem;
import org.hamcrest.core.isA;
import org.hamcrest.object.equalTo;

use namespace dolly_internal;

public class CloningOfCompositeCloneableClassTest {

	private var compositeCloneableClass:CompositeCloneableClass;
	private var compositeCloneableClassType:Type;

	[Before]
	public function before():void {
		compositeCloneableClass = new CompositeCloneableClass();
		compositeCloneableClass.array = [1, 2, 3, 4, 5];
		compositeCloneableClass.arrayList = new ArrayList([1, 2, 3, 4, 5]);
		compositeCloneableClass.arrayCollection = new ArrayCollection([1, 2, 3, 4, 5]);

		compositeCloneableClassType = Type.forInstance(compositeCloneableClass);
	}

	[After]
	public function after():void {
		compositeCloneableClass = null;
		compositeCloneableClassType = null;
	}

	[Test]
	public function findingAllWritableFieldsForType():void {
		const writableFields:Vector.<Field> = Cloner.findAllWritableFieldsForType(compositeCloneableClassType);
		assertNotNull(writableFields);
		assertEquals(4, writableFields.length);
	}

	[Test]
	public function cloningOfArray():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		assertNotNull(clone.array);
		assertThat(clone.array, arrayWithSize(5));
		assertThat(clone.array, compositeCloneableClass.array);
		assertFalse(clone.array == compositeCloneableClass.array);
		assertThat(clone.array, everyItem(isA(Number)));
		assertThat(clone.array, array(equalTo(1), equalTo(2), equalTo(3), equalTo(4), equalTo(5)));
	}

	[Test]
	public function cloningOfArrayList():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		const arrayList:ArrayList = clone.arrayList;

		assertNotNull(arrayList);
		assertFalse(clone.arrayList == compositeCloneableClass.arrayList);
		assertEquals(arrayList.length, 5);
		assertEquals(arrayList.getItemAt(0), 1);
		assertEquals(arrayList.getItemAt(1), 2);
		assertEquals(arrayList.getItemAt(2), 3);
		assertEquals(arrayList.getItemAt(3), 4);
		assertEquals(arrayList.getItemAt(4), 5);
	}

	[Test]
	public function cloningOfArrayCollection():void {
		const clone:CompositeCloneableClass = Cloner.clone(compositeCloneableClass);

		const targetArrayCollection:ArrayCollection = clone.arrayCollection;

		assertNotNull(targetArrayCollection);
		assertFalse(clone.arrayCollection == compositeCloneableClass.arrayCollection);
		assertEquals(targetArrayCollection.length, 5);
		assertEquals(targetArrayCollection.getItemAt(0), 1);
		assertEquals(targetArrayCollection.getItemAt(1), 2);
		assertEquals(targetArrayCollection.getItemAt(2), 3);
		assertEquals(targetArrayCollection.getItemAt(3), 4);
		assertEquals(targetArrayCollection.getItemAt(4), 5);
	}
}
}

Fix typo.

Fix typo.


import mx.transitions.easing.*;
import com.mosesSupposes.fuse.*;

class menuColouridiomes extends MoviieClip

	{
		public var cat, es, en ,fr:MovieClip;
		public var arrayLang_arr:Array = new Array ("cat", "es", "en", "fr");

		function menuColourIdiomes ():Void

		{

		this.onRollOver = this.mOver;
		this.onRollOut = this.mOut;
		this.onRelease =this.mOver;

		}

		private function mOver()

		{

                arrayLang_arr[i].colorTo("#95C60D", 0.3, "easeOutCirc");

		}

		private function mOut()

		{

                arrayLang_arr[i].colorTo("#010101", 0.3, "easeInCirc");

		}

	}

import mx.transitions.easing.*;
import com.mosesSupposes.fuse.*;

class menuColouridiomes extends MovieClip

	{
		public var cat, es, en ,fr:MovieClip;
		public var arrayLang_arr:Array = new Array ("cat", "es", "en", "fr");

		function menuColourIdiomes ():Void

		{

		this.onRollOver = this.mOver;
		this.onRollOut = this.mOut;
		this.onRelease =this.mOver;

		}

		private function mOver()

		{

                arrayLang_arr[i].colorTo("#95C60D", 0.3, "easeOutCirc");

		}

		private function mOut()

		{

                arrayLang_arr[i].colorTo("#010101", 0.3, "easeInCirc");

		}

	}

Update menuColourIdiomes.as

Update menuColourIdiomes.as


package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.geometry.Geometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.scene.controller.mesh.MeshController;
	import aerys.minko.scene.controller.mesh.MeshVisibilityController;
	import aerys.minko.scene.data.TransformDataProvider;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;
	import aerys.minko.type.enum.FrustumCulling;
	import aerys.minko.type.math.Ray;

	use namespace minko_scene;

	/**
	 * Mesh objects are a visible instance of a Geometry rendered using a specific
	 * Effect with specific rendering properties.
	 *
	 *

	 * Those rendering properties are stored in a DataBindings object so they can
	 * be directly used by the shaders in the rendering API.
	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Mesh extends AbstractVisibleSceneNode
	{
		public static const DEFAULT_MATERIAL	: Material	= new BasicMaterial();

		private var _geometry			: Geometry;
		private var _properties			: DataProvider;
		private var _material			: Material;
		private var _bindings			: DataBindings;

		private var _visibility			: MeshVisibilityController;

		private var _frame				: uint;

		private var _cloned				: Signal;
		private var _materialChanged	: Signal;
		private var _frameChanged		: Signal;
		private var _geometryChanged	: Signal;

		/**
		 * A DataProvider object already bound to the Mesh bindings.
		 *
		 *

		 * // set the "diffuseColor" property to 0x0000ffff
		 * mesh.properties.diffuseColor = 0x0000ffff;
		 *
		 * // animate the "diffuseColor" property
		 * mesh.addController(
		 *   new AnimationController(
		 * 	  new <ITimeline>[new ColorTimeline(
		 * 	    "dataProvider.diffuseColor",
		 * 	    5000,
		 * 	    new <uint>[0xffffffff, 0xffffff00, 0xffffffff]
		 *    )]
		 *   )
		 * );
		 *

		 *
		 * @return
		 *
		 */
		public function get properties() : DataProvider
		{
			return _properties;
		}

		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get material() : Material
		{
			return _material;
		}
		public function set material(value : Material) : void
		{
			if (_material != value)
			{
				if (_material)
					_bindings.removeProvider(_material);

				var oldMaterial : Material = _material;

				_material = value;

				if (value)
					_bindings.addProvider(value);

				_materialChanged.execute(this, oldMaterial, value);
			}
		}

		/**
		 * The rendering properties provided to the shaders to customize
		 * how the mesh will appear on screen.
		 *
		 * @return
		 *
		 */
		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The Geometry of the mesh.
		 * @return
		 *
		 */
		public function get geometry() : Geometry
		{
			return _geometry;
		}

		public function set geometry(value : Geometry) : void
		{
			if (_geometry != value)
			{
				var oldGeometry	: Geometry = _geometry;

				if (oldGeometry)
					oldGeometry.changed.remove(geometryChangedHandler);

				_geometry = value;

				if (value)
					_geometry.changed.add(geometryChangedHandler);

				_geometryChanged.execute(this, oldGeometry, value);
			}
		}

        /**
         * Whether the mesh in inside the camera frustum or not.
         * @return
         *
         */
        public function get insideFrustum() : Boolean
        {
            return _visibility.insideFrustum;
        }

        override public function get computedVisibility() : Boolean
        {
            return scene ? _visibility.computedVisibility : super.computedVisibility;
        }

		public function get frustumCulling() : uint
		{
			return _visibility.frustumCulling;
		}
		public function set frustumCulling(value : uint) : void
		{
			_visibility.frustumCulling = value;
		}

		public function get cloned() : Signal
		{
			return _cloned;
		}

		public function get materialChanged() : Signal
		{
			return _materialChanged;
		}

		public function get frameChanged() : Signal
		{
			return _frameChanged;
		}

		public function get geometryChanged() : Signal
		{
			return _geometryChanged;
		}

		public function get frame() : uint
		{
			return _frame;
		}
		public function set frame(value : uint) : void
		{
			if (_frame != value)
			{
				var oldFrame : uint = _frame;

				_frame = value;
				_frameChanged.execute(this, oldFrame, value);
			}
		}

		public function Mesh(geometry	: Geometry	= null,
							 material	: Material	= null,
							 name		: String	= null)
		{
			super();

			initializeMesh(geometry, material, name);
		}

		override protected function initialize() : void
		{
			_bindings = new DataBindings(this);
			this.properties = new DataProvider(
				properties,
				'meshProperties',
				DataProviderUsage.EXCLUSIVE
			);

			super.initialize();
		}

		override protected function initializeSignals():void
		{
			super.initializeSignals();

			_cloned = new Signal('Mesh.cloned');
			_materialChanged = new Signal('Mesh.materialChanged');
			_frameChanged = new Signal('Mesh.frameChanged');
			_geometryChanged = new Signal('Mesh.geometryChanged');
		}

		override protected function initializeContollers():void
		{
			super.initializeContollers();

			addController(new MeshController());

			_visibility = new MeshVisibilityController();
			_visibility.frustumCulling = FrustumCulling.ENABLED;
			addController(_visibility);
		}

		protected function initializeMesh(geometry	: Geometry,
										  material	: Material,
										  name		: String) : void
		{
			if (name)
				this.name = name;

			this.geometry = geometry;
			this.material = material || DEFAULT_MATERIAL;
		}

		public function cast(ray : Ray, maxDistance : Number = Number.POSITIVE_INFINITY) : Number
		{
			return _geometry.boundingBox.testRay(
				ray,
				getWorldToLocalTransform(),
				maxDistance
			);
		}

		override minko_scene function cloneNode() : AbstractSceneNode
		{
			var clone : Mesh = new Mesh();

			clone.name 		= name;
			clone.geometry 	= _geometry;

			clone.properties = DataProvider(_properties.clone());
			clone._bindings.copySharedProvidersFrom(_bindings);

			clone.transform.copyFrom(transform);
			clone.material = _material;

			this.cloned.execute(this, clone);

			return clone;
		}

		private function geometryChangedHandler(geometry : Geometry) : void
		{
			_geometryChanged.execute(this, _geometry, _geometry);
		}
	}
}

package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.geometry.Geometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.scene.controller.mesh.MeshController;
	import aerys.minko.scene.controller.mesh.MeshVisibilityController;
	import aerys.minko.scene.data.TransformDataProvider;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;
	import aerys.minko.type.enum.FrustumCulling;
	import aerys.minko.type.math.Ray;

	use namespace minko_scene;

	/**
	 * Mesh objects are a visible instance of a Geometry rendered using a specific
	 * Effect with specific rendering properties.
	 *
	 *

	 * Those rendering properties are stored in a DataBindings object so they can
	 * be directly used by the shaders in the rendering API.
	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Mesh extends AbstractVisibleSceneNode
	{
		public static const DEFAULT_MATERIAL	: Material	= new BasicMaterial();

		private var _geometry			: Geometry;
		private var _properties			: DataProvider;
		private var _material			: Material;
		private var _bindings			: DataBindings;

		private var _visibility			: MeshVisibilityController;

		private var _frame				: uint;

		private var _cloned				: Signal;
		private var _materialChanged	: Signal;
		private var _frameChanged		: Signal;
		private var _geometryChanged	: Signal;

		/**
		 * A DataProvider object already bound to the Mesh bindings.
		 *
		 *

		 * // set the "diffuseColor" property to 0x0000ffff
		 * mesh.properties.diffuseColor = 0x0000ffff;
		 *
		 * // animate the "diffuseColor" property
		 * mesh.addController(
		 *   new AnimationController(
		 * 	  new <ITimeline>[new ColorTimeline(
		 * 	    "dataProvider.diffuseColor",
		 * 	    5000,
		 * 	    new <uint>[0xffffffff, 0xffffff00, 0xffffffff]
		 *    )]
		 *   )
		 * );
		 *

		 *
		 * @return
		 *
		 */
		public function get properties() : DataProvider
		{
			return _properties;
		}

		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get material() : Material
		{
			return _material;
		}
		public function set material(value : Material) : void
		{
			if (_material != value)
			{
				if (_material)
					_bindings.removeProvider(_material);

				var oldMaterial : Material = _material;

				_material = value;

				if (value)
					_bindings.addProvider(value);

				_materialChanged.execute(this, oldMaterial, value);
			}
		}

		/**
		 * The rendering properties provided to the shaders to customize
		 * how the mesh will appear on screen.
		 *
		 * @return
		 *
		 */
		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The Geometry of the mesh.
		 * @return
		 *
		 */
		public function get geometry() : Geometry
		{
			return _geometry;
		}

		public function set geometry(value : Geometry) : void
		{
			if (_geometry != value)
			{
				var oldGeometry	: Geometry = _geometry;

				if (oldGeometry)
					oldGeometry.changed.remove(geometryChangedHandler);

				_geometry = value;

				if (value)
					_geometry.changed.add(geometryChangedHandler);

				_geometryChanged.execute(this, oldGeometry, value);
			}
		}

        /**
         * Whether the mesh in inside the camera frustum or not.
         * @return
         *
         */
        public function get insideFrustum() : Boolean
        {
            return _visibility.insideFrustum;
        }

        override public function get computedVisibility() : Boolean
        {
            return scene
				? super.computedVisibility && _visibility.computedVisibility
				: super.computedVisibility;
        }

		public function get frustumCulling() : uint
		{
			return _visibility.frustumCulling;
		}
		public function set frustumCulling(value : uint) : void
		{
			_visibility.frustumCulling = value;
		}

		public function get cloned() : Signal
		{
			return _cloned;
		}

		public function get materialChanged() : Signal
		{
			return _materialChanged;
		}

		public function get frameChanged() : Signal
		{
			return _frameChanged;
		}

		public function get geometryChanged() : Signal
		{
			return _geometryChanged;
		}

		public function get frame() : uint
		{
			return _frame;
		}
		public function set frame(value : uint) : void
		{
			if (_frame != value)
			{
				var oldFrame : uint = _frame;

				_frame = value;
				_frameChanged.execute(this, oldFrame, value);
			}
		}

		public function Mesh(geometry	: Geometry	= null,
							 material	: Material	= null,
							 name		: String	= null)
		{
			super();

			initializeMesh(geometry, material, name);
		}

		override protected function initialize() : void
		{
			_bindings = new DataBindings(this);
			this.properties = new DataProvider(
				properties,
				'meshProperties',
				DataProviderUsage.EXCLUSIVE
			);

			super.initialize();
		}

		override protected function initializeSignals():void
		{
			super.initializeSignals();

			_cloned = new Signal('Mesh.cloned');
			_materialChanged = new Signal('Mesh.materialChanged');
			_frameChanged = new Signal('Mesh.frameChanged');
			_geometryChanged = new Signal('Mesh.geometryChanged');
		}

		override protected function initializeContollers():void
		{
			super.initializeContollers();

			addController(new MeshController());

			_visibility = new MeshVisibilityController();
			_visibility.frustumCulling = FrustumCulling.ENABLED;
			addController(_visibility);
		}

		protected function initializeMesh(geometry	: Geometry,
										  material	: Material,
										  name		: String) : void
		{
			if (name)
				this.name = name;

			this.geometry = geometry;
			this.material = material || DEFAULT_MATERIAL;
		}

		public function cast(ray : Ray, maxDistance : Number = Number.POSITIVE_INFINITY) : Number
		{
			return _geometry.boundingBox.testRay(
				ray,
				getWorldToLocalTransform(),
				maxDistance
			);
		}

		override minko_scene function cloneNode() : AbstractSceneNode
		{
			var clone : Mesh = new Mesh();

			clone.name 		= name;
			clone.geometry 	= _geometry;

			clone.properties = DataProvider(_properties.clone());
			clone._bindings.copySharedProvidersFrom(_bindings);

			clone.transform.copyFrom(transform);
			clone.material = _material;

			this.cloned.execute(this, clone);

			return clone;
		}

		private function geometryChangedHandler(geometry : Geometry) : void
		{
			_geometryChanged.execute(this, _geometry, _geometry);
		}
	}
}

fix Mesh.computedVisibility getter to combine frustum culling and parent/self computed visibility properly using super.computedVisibility (github issue #77)


package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.geometry.Geometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.scene.controller.mesh.VisibilityController;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.enum.FrustumCulling;
	import aerys.minko.type.enum.DataProviderUsage;
	import aerys.minko.type.math.Ray;

	use namespace minko_scene;

	/**
	 * Mesh objects are a visible instance of a Geometry rendered using a specific
	 * Effect with specific rendering properties.
	 *
	 *

	 * Those rendering properties are stored in a DataBindings object so they can
	 * be directly used by the shaders in the rendering API.
	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Mesh extends AbstractSceneNode
	{
		public static const DEFAULT_MATERIAL	: Material	= new BasicMaterial();

		private var _geometry			: Geometry;
		private var _properties			: DataProvider;
		private var _material			: Material;
		private var _bindings			: DataBindings;

		private var _visibility			: VisibilityController;

		private var _frame				: uint;

		private var _cloned				: Signal;
		private var _materialChanged	: Signal;
		private var _frameChanged		: Signal;
		private var _geometryChanged	: Signal;

		/**
		 * A DataProvider object already bound to the Mesh bindings.
		 *
		 *

		 * // set the "diffuseColor" property to 0x0000ffff
		 * mesh.properties.diffuseColor = 0x0000ffff;
		 *
		 * // animate the "diffuseColor" property
		 * mesh.addController(
		 *   new AnimationController(
		 * 	  new <ITimeline>[new ColorTimeline(
		 * 	    "dataProvider.diffuseColor",
		 * 	    5000,
		 * 	    new <uint>[0xffffffff, 0xffffff00, 0xffffffff]
		 *    )]
		 *   )
		 * );
		 *

		 *
		 * @return
		 *
		 */
		public function get properties() : DataProvider
		{
			return _properties;
		}

		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get material() : Material
		{
			return _material;
		}
		public function set material(value : Material) : void
		{
			if (_material != value)
			{
				if (_material)
					_bindings.removeProvider(_material);

				var oldMaterial : Material = _material;

				_material = value;

				if (value)
					_bindings.addProvider(value);

				_materialChanged.execute(this, oldMaterial, value);
			}
		}

		/**
		 * The rendering properties provided to the shaders to customize
		 * how the mesh will appear on screen.
		 *
		 * @return
		 *
		 */
		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The Geometry of the mesh.
		 * @return
		 *
		 */
		public function get geometry() : Geometry
		{
			return _geometry;
		}

		public function set geometry(value : Geometry) : void
		{
			if (_geometry != value)
			{
				var oldGeometry	: Geometry = _geometry;

				if (oldGeometry)
					oldGeometry.changed.remove(geometryChangedHandler);

				_geometry = value;

				if (value)
					_geometry.changed.add(geometryChangedHandler);

				_geometryChanged.execute(this, oldGeometry, value);
			}
		}

		/**
		 * Whether the mesh is visible or not.
		 *
		 * @return
		 *
		 */
		public function get visible() : Boolean
		{
			return _visibility.visible;
		}
		public function set visible(value : Boolean) : void
		{
			_visibility.visible = value;
		}

		public function get frustumCulling() : uint
		{
			return _visibility.frustumCulling;
		}
		public function set frustumCulling(value : uint) : void
		{
			_visibility.frustumCulling = value;
		}

		public function get cloned() : Signal
		{
			return _cloned;
		}

		public function get materialChanged() : Signal
		{
			return _materialChanged;
		}

		public function get frameChanged() : Signal
		{
			return _frameChanged;
		}

		public function get geometryChanged() : Signal
		{
			return _geometryChanged;
		}

		public function get frame() : uint
		{
			return _frame;
		}
		public function set frame(value : uint) : void
		{
			if (_frame != value)
			{
				var oldFrame : uint = _frame;

				_frame = value;
				_frameChanged.execute(this, oldFrame, value);
			}
		}

		public function Mesh(geometry	: Geometry	= null,
							 material	: Material	= null,
							 name		: String	= null)
		{
			super();

			initialize(geometry, material, name);
		}

		private function initialize(geometry	: Geometry,
									material	: Material,
									name		: String) : void
		{
			if (name)
				this.name = name;

			_cloned = new Signal('Mesh.clones');
			_materialChanged = new Signal('Mesh.materialChanged');
			_frameChanged = new Signal('Mesh.frameChanged');
			_geometryChanged = new Signal('Mesh.geometryChanged');

			_bindings = new DataBindings(this);
			this.properties = new DataProvider(properties, 'meshProperties', DataProviderUsage.EXCLUSIVE);

			this.geometry = geometry;
			this.material = material || DEFAULT_MATERIAL;

			_visibility = new VisibilityController();
			_visibility.frustumCulling = FrustumCulling.ENABLED;
			addController(_visibility);
		}

		public function cast(ray : Ray, maxDistance : Number = Number.POSITIVE_INFINITY) : Number
		{
			return _geometry.boundingBox.testRay(
				ray,
				worldToLocal,
				maxDistance
			);
		}

		override minko_scene function cloneNode() : AbstractSceneNode
		{
			var clone : Mesh = new Mesh();

			clone.name 		= name;
			clone.geometry 	= _geometry;

			clone.properties = DataProvider(_properties.clone());
			clone._bindings.copySharedProvidersFrom(_bindings);

			clone.transform.copyFrom(transform);
			clone.material = _material;

			this.cloned.execute(this, clone);

			return clone;
		}

		private function geometryChangedHandler(geometry : Geometry) : void
		{
			_geometryChanged.execute(this, _geometry, _geometry);
		}
	}
}

package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.render.geometry.Geometry;
	import aerys.minko.render.material.Material;
	import aerys.minko.render.material.basic.BasicMaterial;
	import aerys.minko.scene.controller.mesh.VisibilityController;
	import aerys.minko.type.Signal;
	import aerys.minko.type.binding.DataBindings;
	import aerys.minko.type.binding.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;
	import aerys.minko.type.enum.FrustumCulling;
	import aerys.minko.type.math.Ray;

	use namespace minko_scene;

	/**
	 * Mesh objects are a visible instance of a Geometry rendered using a specific
	 * Effect with specific rendering properties.
	 *
	 *

	 * Those rendering properties are stored in a DataBindings object so they can
	 * be directly used by the shaders in the rendering API.
	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Mesh extends AbstractSceneNode
	{
		public static const DEFAULT_MATERIAL	: Material	= new BasicMaterial();

		private var _geometry			: Geometry;
		private var _properties			: DataProvider;
		private var _material			: Material;
		private var _bindings			: DataBindings;

		private var _visibility			: VisibilityController;

		private var _frame				: uint;

		private var _cloned				: Signal;
		private var _materialChanged	: Signal;
		private var _frameChanged		: Signal;
		private var _geometryChanged	: Signal;

		/**
		 * A DataProvider object already bound to the Mesh bindings.
		 *
		 *

		 * // set the "diffuseColor" property to 0x0000ffff
		 * mesh.properties.diffuseColor = 0x0000ffff;
		 *
		 * // animate the "diffuseColor" property
		 * mesh.addController(
		 *   new AnimationController(
		 * 	  new <ITimeline>[new ColorTimeline(
		 * 	    "dataProvider.diffuseColor",
		 * 	    5000,
		 * 	    new <uint>[0xffffffff, 0xffffff00, 0xffffffff]
		 *    )]
		 *   )
		 * );
		 *

		 *
		 * @return
		 *
		 */
		public function get properties() : DataProvider
		{
			return _properties;
		}

		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get material() : Material
		{
			return _material;
		}
		public function set material(value : Material) : void
		{
			if (_material != value)
			{
				if (_material)
					_bindings.removeProvider(_material);

				var oldMaterial : Material = _material;

				_material = value;

				if (value)
					_bindings.addProvider(value);

				_materialChanged.execute(this, oldMaterial, value);
			}
		}

		/**
		 * The rendering properties provided to the shaders to customize
		 * how the mesh will appear on screen.
		 *
		 * @return
		 *
		 */
		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The Geometry of the mesh.
		 * @return
		 *
		 */
		public function get geometry() : Geometry
		{
			return _geometry;
		}

		public function set geometry(value : Geometry) : void
		{
			if (_geometry != value)
			{
				var oldGeometry	: Geometry = _geometry;

				if (oldGeometry)
					oldGeometry.changed.remove(geometryChangedHandler);

				_geometry = value;

				if (value)
					_geometry.changed.add(geometryChangedHandler);

				_geometryChanged.execute(this, oldGeometry, value);
			}
		}

		/**
		 * Whether the mesh is visible or not.
		 *
		 * @return
		 *
		 */
		public function get visible() : Boolean
		{
			return _visibility.visible;
		}
		public function set visible(value : Boolean) : void
		{
			_visibility.visible = value;
		}

        /**
         * Whether the mesh in inside the camera frustum or not.
         * @return
         *
         */
        public function get insideFrustum() : Boolean
        {
            return _visibility.insideFrustum;
        }

        public function get computedVisibility() : Boolean
        {
            return _visibility.computedVisibility;
        }

		public function get frustumCulling() : uint
		{
			return _visibility.frustumCulling;
		}
		public function set frustumCulling(value : uint) : void
		{
			_visibility.frustumCulling = value;
		}

		public function get cloned() : Signal
		{
			return _cloned;
		}

		public function get materialChanged() : Signal
		{
			return _materialChanged;
		}

		public function get frameChanged() : Signal
		{
			return _frameChanged;
		}

		public function get geometryChanged() : Signal
		{
			return _geometryChanged;
		}

		public function get frame() : uint
		{
			return _frame;
		}
		public function set frame(value : uint) : void
		{
			if (_frame != value)
			{
				var oldFrame : uint = _frame;

				_frame = value;
				_frameChanged.execute(this, oldFrame, value);
			}
		}

		public function Mesh(geometry	: Geometry	= null,
							 material	: Material	= null,
							 name		: String	= null)
		{
			super();

			initialize(geometry, material, name);
		}

		private function initialize(geometry	: Geometry,
									material	: Material,
									name		: String) : void
		{
			if (name)
				this.name = name;

			_cloned = new Signal('Mesh.clones');
			_materialChanged = new Signal('Mesh.materialChanged');
			_frameChanged = new Signal('Mesh.frameChanged');
			_geometryChanged = new Signal('Mesh.geometryChanged');

			_bindings = new DataBindings(this);
			this.properties = new DataProvider(properties, 'meshProperties', DataProviderUsage.EXCLUSIVE);

			this.geometry = geometry;
			this.material = material || DEFAULT_MATERIAL;

			_visibility = new VisibilityController();
			_visibility.frustumCulling = FrustumCulling.ENABLED;
			addController(_visibility);
		}

		public function cast(ray : Ray, maxDistance : Number = Number.POSITIVE_INFINITY) : Number
		{
			return _geometry.boundingBox.testRay(
				ray,
				worldToLocal,
				maxDistance
			);
		}

		override minko_scene function cloneNode() : AbstractSceneNode
		{
			var clone : Mesh = new Mesh();

			clone.name 		= name;
			clone.geometry 	= _geometry;

			clone.properties = DataProvider(_properties.clone());
			clone._bindings.copySharedProvidersFrom(_bindings);

			clone.transform.copyFrom(transform);
			clone.material = _material;

			this.cloned.execute(this, clone);

			return clone;
		}

		private function geometryChangedHandler(geometry : Geometry) : void
		{
			_geometryChanged.execute(this, _geometry, _geometry);
		}
	}
}

add Mesh.insideFrustum and Mesh.computedVisibility properties