/******************************************************************************
 * LzMediaLoader.as
 *****************************************************************************/

//* A_LZ_COPYRIGHT_BEGIN ******************************************************
//* Copyright 2001-2006 Laszlo Systems, Inc.  All Rights Reserved.            *
//* Use is subject to license terms.                                          *
//* A_LZ_COPYRIGHT_END ********************************************************

//==============================================================================
// DEFINE OBJECT: LzMediaLoader
// @keywords private
//==============================================================================
LzMediaLoader = Class(
    "LzMediaLoader",
    LzLoader,
    function ( owner , args ) {
        #pragma 'methodName=constructor'
        super( owner ,args );

        this.owner.loadperc = 0;

        this.loadChecker = new _root.LzDelegate( this , "testLoad" );

        this.removeLoadCheckerDel =
            new _root.LzDelegate( this,
                                  "removeLoadChecker", this, "onloaddone" );

        this.timeout = canvas.medialoadtimeout;

        //setup loadmovie stuff that never changes
        this.mc.loader = this;
        this.mc.mc = this.mc;
        this.mc.timeout = this.timeout;
        this.lastrequest = this.mc;
        // [2005-08-28] We use the view's clip as the loadobj, so
        // monitor it (as we would in LzLoader if we created a new
        // loadobj).
        if ($debug) {
            LzLoader.debugLoadObj(this.mc, 'MediaLoadObj');
        }
    }
);

LzMediaLoader.prototype.LOADERDEPTH = 9;

//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.removeLoadChecker = function() {
    // Remove loadChecker delegate
    this.loadChecker.unregisterAll();
    this.removeLoadCheckerDel.unregisterAll();
}

//==============================================================================
// @keywords private
// [2005-08-29 ptw] It appears the intent here is that there is 1
// media loader per view with a resource, so we use the view's
// movieclip as the loadmovie, rather than creating another.
//==============================================================================
LzMediaLoader.prototype.getLoadMovie = function ( ){
    // Abort any load in progress
    this.unload( this.mc );
    if (this.isaudio != true && this._oldmc != null) {
        // restore regular loader if audio was used before.
        this.mc.unload();
        var m = this._oldmc;
        this._oldmc = null;
        this.mc = m;
    } else if (this.isaudio == true && this._oldmc == null) {
        this._oldmc = this.mc;
        this.mc = new SoundMC(this.mc);
        this.initializeRequestObj(mc);
        if ($debug) {
            LzLoader.debugLoadObj(this.mc, 'MediaLoadObj');
        }
        //_root.Debug.warn('getLoadMovie lmc %w %w', this.mc, this.mc.lmc)
    } else {
        //_root.Debug.warn('getLoadMovie not audio %2 %w', this.mc, this.mc.lmc)
    }

    // return the view's clip
    return this.mc;
}

//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.attachLoadMovie = function ( resc ){
    var mc = this.getLoadMovie();
    //Debug.warn('attachLoadMovie %w %w %w', resc, mc, this._oldmc)
    if (this.isaudio == true && this._oldmc != null) {
        // restore regular loader if audio was used before.
        this.mc.unload();
        var m = this._oldmc;
        this._oldmc = null;
        this.mc = m;
        mc = m;
    }
    if (resc) {
        mc.attachMovie( resc , "lmc", this.LOADERDEPTH );
        if (this.mc.loading == true) LzLoadQueue.loadFinished( mc );
    } else {
        Debug.error('%w.attachMovie(%w)', this, resc);
    }
}

//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.startingLoad = function ( loadmc ){
    this.checkonce = false;
    this.loadChecker.register( _root.LzIdle, "onidle" );
}

//=============================================================================
// Media types which cannot be loaded directly (serverless) at runtime.
//
// We use a blacklist instead of a whitelist, because the user may
// want to access a URL which generates a supported format, but has an
// suffix from which it is not possible to deduce the file type, like
// .jsp or .php.
LzMediaLoader.unsupportedMediaTypes = {
    "bmp": true,
    "tiff": true,
    "tif": true,
    "wmf": true,
    "wmv": true

};

LzMediaLoader.unsupportedMediaTypesSWF7 = {
    "png": true,
    "gif": true
}

//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.request = function( req , cache , headers ) {
    var o = { url: req , lzt: "media", timeout: this.timeout };

    if ( cache == "none" ){
        o.cache = false;
        o.ccache = false;
    } else if ( cache == "clientonly" ){
        o.cache = false;
        o.ccache = true;
    } else if ( cache == "serveronly" ){
        o.cache = true;
        o.ccache = false;
    } else {
        o.cache = true;
        o.ccache = true;
    }

    var policy = _root.LzView.__LZcheckProxyPolicy( req );
    this.proxied = policy;
    o.proxied = policy;

    if (!this.proxied) {
        // warn for unsupported media types
        var suffix = null;
        var si = req.lastIndexOf(".");
        if (si != -1) {
            suffix = req.substring(si+1, si.length).toLowerCase();
        }
        if ($debug) {
            if (suffix != null && ((LzMediaLoader.unsupportedMediaTypes[suffix] == true)
                                   ||
                                   ((canvas.runtime == "swf7" || canvas.runtime == "swf6")
                                    && (LzMediaLoader.unsupportedMediaTypesSWF7[suffix] == true)))) {
                _root.Debug.write("WARNING: serverless loading of resources with type '"
                                + suffix + "' is not supported by the Flash player. " +
                                req);
            }
        }
        if (suffix == 'mp3') {
            this.isaudio = true;
        } else {
            this.isaudio = false;
        }
        //_root.Debug.write('suffix', suffix, this.isaudio);
    }

    if ( headers != null ) o.headers = headers;
    super.request( o );
    this.owner.setAttribute( "framesloadratio" , 0 );
    this.owner.setAttribute( "loadratio" , 0 );
}

//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.testLoad = function (){
    //skip first check because this can get called before load starts, in
    //which case load info is wrong
    //getBytesTotal is wrong before the header of the movie has loaded

    /*
    _root.Debug.write('%w %w %w %w %w %w %w %w %w', this.mc.lmc, typeof(this.mc.lmc.getBytesTotal),
                      this.mc.lmc.getBytesLoaded(), typeof(this.mc.lmc.getBytesLoaded()),
                      this.mc.lmc.getBytesTotal(), typeof(this.mc.lmc.getBytesTotal()),
                      this.mc.lmc._currentframe, this.mc.lmc._framesloaded, this.mc.lmc._totalframes);
*/
    if ( this.checkonce ){
        var lr = this.mc.lmc.getBytesLoaded() / this.mc.lmc.getBytesTotal();
        if (lr != this.owner["loadratio"]) {
            this.owner.setAttribute("loadratio" , lr);
            //reset timeout for media which is streaming
            this.mc.loadtime = getTimer();
        }
    }

    if ( this.checkonce && this.mc.lmc.getBytesTotal == void 0
         && this.mc.lmc._totalframes > 0  ) {
             //a swf loaded from another domain will be sandboxed. no load
             //information is available;
             if ( !this.sentLoadStart ){
                 this.sentLoadStart = true;
                 if ( ! this.mc.loaded ) {
                     this.onstreamstart.sendEvent( this );
                 }
             }

             var nlp = this.mc.lmc._framesloaded /
             this.mc.lmc._totalframes;

             if ( nlp > this.owner.loadperc ){
                 //reset timeout for media which is streaming
                 //_root.Debug.write( "here" , this.mc.lmc._framesloaded ,
                 //this.mc.lmc._totalframes );

                 if (this.mc.lmc._totalframes > 0) {
                     var nlp = this.mc.lmc._framesloaded /
                         this.mc.lmc._totalframes;

                     if ( nlp > this.owner.loadperc ){
                         //reset timeout for media which is streaming
                         this.mc.loadtime = getTimer();
                     }

                     this.owner.loadperc = nlp;
                     this.owner.onloadperc.sendEvent( this.owner.loadperc );
                     this.owner.setAttribute( "framesloadratio" , nlp );
                     this.owner.setAttribute( "loadratio" , nlp );

                     if ( this.mc.lmc._totalframes == this.mc.lmc._framesloaded){
                         this.onloaddone.sendEvent( this );
                         this.returnData( this.mc );
                     }
                 }
             }
         }

    if ( this.checkonce && this.mc.lmc._currentframe > 0
         && typeof(this.mc.lmc.getBytesTotal) != "undefined"
         && this.mc.lmc.getBytesTotal() > this.minHeader ) {

             if ( !this.sentLoadStart ){
                 this.sentLoadStart = true;
                 //this assumes that an error swf will have already called back
                 //into the LFC by the time the load is detected. If this is
                 //wrong, then the view will send both onload and onrror.
                 if ( ! this.mc.loaded ) {
                     this.onstreamstart.sendEvent( this );
                 }
             }

             if (this.mc.lmc._totalframes > 0) {
                 var nlp = this.mc.lmc._framesloaded /
                 this.mc.lmc._totalframes;

                 if ( nlp > this.owner.loadperc ){
                     //reset timeout for media which is streaming
                     this.mc.loadtime = getTimer();
                 }

                 this.owner.loadperc = nlp;
                 this.owner.onloadperc.sendEvent( this.owner.loadperc );
                 this.owner.setAttribute( "framesloadratio" , nlp );
             }

             if ( this.mc.lmc.getBytesTotal() == this.mc.lmc.getBytesLoaded() ){
                 //load is done

                 this.onloaddone.sendEvent( this );
                 //if mc.loaded is set, means returnData has already been called
                 //(probably by error swf.)
                 if ( !this.mc.loaded ){
                     this.returnData( this.mc );
                 }
             }
         }

    if ( !this.checkonce ){
        this.sentLoadStart = false;
        this.checkonce = true;
    }
}
//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.unload= function ( loadobj ){
    super.unload( loadobj );
    if ( this.owner.loadratio != 0 ){
        this.owner.loadperc = 0;
        this.owner.onloadperc.sendEvent( 0 );
        this.owner.setAttribute( "loadratio" , 0 );
        this.owner.setAttribute( "framesloadratio" , 0 );
    }

    this.removeLoadChecker();
}

//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.getLoadMC= function (){
    return this.mc.lmc;
}

/******************************************************************************
 * LzMediaLoader.as
 *****************************************************************************/

//* A_LZ_COPYRIGHT_BEGIN ******************************************************
//* Copyright 2001-2006 Laszlo Systems, Inc.  All Rights Reserved.            *
//* Use is subject to license terms.                                          *
//* A_LZ_COPYRIGHT_END ********************************************************

//==============================================================================
// DEFINE OBJECT: LzMediaLoader
// @keywords private
//==============================================================================
LzMediaLoader = Class(
    "LzMediaLoader",
    LzLoader,
    function ( owner , args ) {
        #pragma 'methodName=constructor'
        super( owner ,args );

        this.owner.loadperc = 0;

        this.loadChecker = new _root.LzDelegate( this , "testLoad" );

        this.removeLoadCheckerDel =
            new _root.LzDelegate( this,
                                  "removeLoadChecker", this, "onloaddone" );

        this.timeout = canvas.medialoadtimeout;

        //setup loadmovie stuff that never changes
        this.mc.loader = this;
        this.mc.mc = this.mc;
        this.mc.timeout = this.timeout;
        this.lastrequest = this.mc;
        // [2005-08-28] We use the view's clip as the loadobj, so
        // monitor it (as we would in LzLoader if we created a new
        // loadobj).
        if ($debug) {
            LzLoader.debugLoadObj(this.mc, 'MediaLoadObj');
        }
    }
);

LzMediaLoader.prototype.LOADERDEPTH = 9;

//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.removeLoadChecker = function() {
    // Remove loadChecker delegate
    this.loadChecker.unregisterAll();
    this.removeLoadCheckerDel.unregisterAll();
}

//==============================================================================
// @keywords private
// [2005-08-29 ptw] It appears the intent here is that there is 1
// media loader per view with a resource, so we use the view's
// movieclip as the loadmovie, rather than creating another.
//==============================================================================
LzMediaLoader.prototype.getLoadMovie = function ( ){
    // Abort any load in progress
    this.unload( this.mc );
    if (this.isaudio != true && this._oldmc != null) {
        // restore regular loader if audio was used before.
        this.mc.unload();
        var m = this._oldmc;
        this._oldmc = null;
        this.mc = m;
    } else if (this.isaudio == true && this._oldmc == null) {
        this._oldmc = this.mc;
        this.mc = new SoundMC(this.mc);
        this.initializeRequestObj(mc);
        if ($debug) {
            LzLoader.debugLoadObj(this.mc, 'MediaLoadObj');
        }
        //_root.Debug.warn('getLoadMovie lmc %w %w', this.mc, this.mc.lmc)
    } else {
        //_root.Debug.warn('getLoadMovie not audio %2 %w', this.mc, this.mc.lmc)
    }

    // return the view's clip
    return this.mc;
}

//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.attachLoadMovie = function ( resc ){
    var mc = this.getLoadMovie();
    //Debug.warn('attachLoadMovie %w %w %w', resc, mc, this._oldmc)
    if (this.isaudio == true && this._oldmc != null) {
        // restore regular loader if audio was used before.
        this.mc.unload();
        var m = this._oldmc;
        this._oldmc = null;
        this.mc = m;
        mc = m;
    }
    if (resc) {
        mc.attachMovie( resc , "lmc", this.LOADERDEPTH );
        if (this.mc.loading == true) {
            Debug.error('already loading', this.mc);
            LzLoadQueue.loadFinished( mc );
        }
    } else {
        Debug.error('%w.attachMovie(%w)', this, resc);
    }
}

//==============================================================================
// @keywords private
//==============================================================================

LzMediaLoader.prototype.startingLoad = function ( loadmc ){
    this.checkonce = false;
    this.loadChecker.register( LzIdle, "onidle" );
    this.removeLoadCheckerDel.register( this, "onloaddone" );
}

//=============================================================================
// Media types which cannot be loaded directly (serverless) at runtime.
//
// We use a blacklist instead of a whitelist, because the user may
// want to access a URL which generates a supported format, but has an
// suffix from which it is not possible to deduce the file type, like
// .jsp or .php.
LzMediaLoader.unsupportedMediaTypes = {
    "bmp": true,
    "tiff": true,
    "tif": true,
    "wmf": true,
    "wmv": true

};

LzMediaLoader.unsupportedMediaTypesSWF7 = {
    "png": true,
    "gif": true
}

//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.request = function( req , cache , headers ) {
    var o = { url: req , lzt: "media", timeout: this.timeout };

    if ( cache == "none" ){
        o.cache = false;
        o.ccache = false;
    } else if ( cache == "clientonly" ){
        o.cache = false;
        o.ccache = true;
    } else if ( cache == "serveronly" ){
        o.cache = true;
        o.ccache = false;
    } else {
        o.cache = true;
        o.ccache = true;
    }

    var policy = _root.LzView.__LZcheckProxyPolicy( req );
    this.proxied = policy;
    o.proxied = policy;

    if (!this.proxied) {
        // warn for unsupported media types
        var suffix = null;
        var si = req.lastIndexOf(".");
        if (si != -1) {
            suffix = req.substring(si+1, si.length).toLowerCase();
        }
        if ($debug) {
            if (suffix != null && ((LzMediaLoader.unsupportedMediaTypes[suffix] == true)
                                   ||
                                   ((canvas.runtime == "swf7" || canvas.runtime == "swf6")
                                    && (LzMediaLoader.unsupportedMediaTypesSWF7[suffix] == true)))) {
                _root.Debug.write("WARNING: serverless loading of resources with type '"
                                + suffix + "' is not supported by the Flash player. " +
                                req);
            }
        }
        if (suffix == 'mp3') {
            this.isaudio = true;
        } else {
            this.isaudio = false;
        }
        //_root.Debug.write('suffix', suffix, this.isaudio);
    }

    if ( headers != null ) o.headers = headers;
    super.request( o );
    this.owner.setAttribute( "framesloadratio" , 0 );
    this.owner.setAttribute( "loadratio" , 0 );
}

//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.testLoad = function (){
    //skip first check because this can get called before load starts, in
    //which case load info is wrong
    //getBytesTotal is wrong before the header of the movie has loaded

    /*
    Debug.write('%w %w %w %w %w %w %w %w %w', this.mc.lmc, typeof(this.mc.lmc.getBytesTotal),
                      this.mc.lmc.getBytesLoaded(), typeof(this.mc.lmc.getBytesLoaded()),
                      this.mc.lmc.getBytesTotal(), typeof(this.mc.lmc.getBytesTotal()),
                      this.mc.lmc._currentframe, this.mc.lmc._framesloaded, this.mc.lmc._totalframes);
    */

    if ( this.isjpeg && this.mc.lmc._height <= 0) {
        //Debug.error('skipping 0 height jpeg');
        return;
    }

    if ( this.checkonce ){
        var lr = this.mc.lmc.getBytesLoaded() / this.mc.lmc.getBytesTotal();
        if (lr != this.owner["loadratio"] && !isNaN(lr)) {
            this.owner.setAttribute("loadratio" , lr);
            //reset timeout for media which is streaming
            this.mc.loadtime = getTimer();
        }
    }

    if ( this.checkonce && this.mc.lmc.getBytesTotal == void 0
         && this.mc.lmc._totalframes > 0  ) {
             //a swf loaded from another domain will be sandboxed. no load
             //information is available;
             if ( !this.sentLoadStart ){
                 this.sentLoadStart = true;
                 if ( ! this.mc.loaded ) {
                     this.onstreamstart.sendEvent( this );
                 }
             }

             var nlp = this.mc.lmc._framesloaded /
             this.mc.lmc._totalframes;

             if ( nlp >= this.owner.loadperc ){
                 //reset timeout for media which is streaming
                 //Debug.write( "here" , this.mc.lmc._framesloaded ,
                 //this.mc.lmc._totalframes );

                 if (this.mc.lmc._totalframes > 0) {
                     var nlp = this.mc.lmc._framesloaded /
                         this.mc.lmc._totalframes;

                     if ( nlp > this.owner.loadperc ){
                         //reset timeout for media which is streaming
                         this.mc.loadtime = getTimer();
                     }

                     this.owner.loadperc = nlp;
                     this.owner.onloadperc.sendEvent( this.owner.loadperc );
                     this.owner.setAttribute( "framesloadratio" , nlp );
                     this.owner.setAttribute( "loadratio" , nlp );

                     if ( this.mc.lmc._totalframes == this.mc.lmc._framesloaded){
                         this.onloaddone.sendEvent( this );
                         this.returnData( this.mc );
                     }
                 }
             }
         }

    if ( this.checkonce && this.mc.lmc._currentframe > 0
         && typeof(this.mc.lmc.getBytesTotal) != "undefined"
         && this.mc.lmc.getBytesTotal() > this.minHeader ) {

             if ( !this.sentLoadStart ){
                 this.sentLoadStart = true;
                 //this assumes that an error swf will have already called back
                 //into the LFC by the time the load is detected. If this is
                 //wrong, then the view will send both onload and onrror.
                 if ( ! this.mc.loaded ) {
                     this.onstreamstart.sendEvent( this );
                 }
             }

             if (this.mc.lmc._totalframes > 0) {
                 var nlp = this.mc.lmc._framesloaded /
                 this.mc.lmc._totalframes;

                 if ( nlp > this.owner.loadperc ){
                     //reset timeout for media which is streaming
                     this.mc.loadtime = getTimer();
                 }

                 this.owner.loadperc = nlp;
                 this.owner.onloadperc.sendEvent( this.owner.loadperc );
                 this.owner.setAttribute( "framesloadratio" , nlp );
             }

             if ( this.mc.lmc.getBytesTotal() == this.mc.lmc.getBytesLoaded() ){
                 //load is done

                 this.onloaddone.sendEvent( this );
                 //if mc.loaded is set, means returnData has already been called
                 //(probably by error swf.)
                 if ( !this.mc.loaded ){
                     this.returnData( this.mc );
                 }
             }
         }

    if ( !this.checkonce ){
        this.sentLoadStart = false;
        this.checkonce = true;
    }
}
//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.unload= function ( loadobj ){
    super.unload( loadobj );
    if ( this.owner.loadratio != 0 ){
        this.owner.loadperc = 0;
        this.owner.onloadperc.sendEvent( 0 );
        this.owner.setAttribute( "loadratio" , 0 );
        this.owner.setAttribute( "framesloadratio" , 0 );
    }

    this.removeLoadChecker();
}

//==============================================================================
// @keywords private
//==============================================================================
LzMediaLoader.prototype.getLoadMC= function (){
    return this.mc.lmc;
}

Change change.BGFgJ2908.txt by hqm@IBM-AA473F7AA76 /home/hqm/src/svn/openlaszlo/trunk/WEB-INF/lps/lfc/ on 2006-09-25 13:04:28 EDT

Summary: fix bug 2732, load checker in media loader leaves idle tasks running

New Features:

Bugs Fixed: LPP-2732 load tester delegate doesn't get removed

Technical Reviewer: adam (pending)
QA Reviewer: (pending)
Doc Reviewer: (pending)

Documentation:

Release Notes:

Details:

This bug doesn't happen in legals, so I back-ported the LzMediaLoader load checker code
from legals to trunk.

Tests:

test case in bug report

git-svn-id: d62bde4b5aa582fdf07c8d403e53e0399a7ed285@1916 fa20e4f9-1d0a-0410-b5f3-dc9c16b8b17c


package aerys.minko.render.resource
{
	import aerys.minko.ns.minko_stream;
	import aerys.minko.type.Signal;
	import aerys.minko.render.geometry.stream.IVertexStream;
	import aerys.minko.render.geometry.stream.StreamUsage;
	import aerys.minko.render.geometry.stream.VertexStream;

	import flash.display3D.Context3D;
	import flash.display3D.VertexBuffer3D;

	/**
	 * VertexBuffer3DResource objects handle vertex buffers allocation
	 * and disposal using the Stage3D API.
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public final class VertexBuffer3DResource implements IResource
	{
		use namespace minko_stream;

		private var _stream			: VertexStream		= null;
		private var _update			: Boolean			= true;
		private var _lengthChanged	: Boolean			= true;
		private var _vertexBuffer	: VertexBuffer3D	= null;
		private var _numVertices	: uint				= 0;

		private var _disposed		: Boolean			= false;

		private var _uploaded		: Signal			= new Signal('VertexBuffer3DRessource.uploaded');

		public function get uploaded() : Signal
		{
			return _uploaded;
		}

		public function get numVertices() : uint
		{
			return _numVertices;
		}

		public function VertexBuffer3DResource(source : VertexStream)
		{
			_stream = source;
			_stream.changed.add(vertexStreamChangedHandler);
		}

		private function vertexStreamChangedHandler(vertexStream : VertexStream) : void
		{
			_update = true;
			_lengthChanged = vertexStream.numVertices != _numVertices;
		}

		public function getVertexBuffer3D(context : Context3DResource) : VertexBuffer3D
		{
			var update	: Boolean	= _update;

			if (_disposed)
				throw new Error('Unable to render a disposed buffer.');

			if (_lengthChanged)
			{
				_lengthChanged = false;
				_numVertices = _stream.numVertices;

				if (_vertexBuffer)
					_vertexBuffer.dispose();

				_vertexBuffer = context.createVertexBuffer(
					_numVertices,
					_stream.format.numBytesPerVertex >>> 2
				);

				update = true;
			}

			if (_vertexBuffer != null && update)
			{
				_vertexBuffer.uploadFromByteArray(_stream._data, 0, 0, _numVertices);
				_uploaded.execute(this);

				_update = false;

				if (!(_stream.usage & StreamUsage.READ) || _stream._localDispose)
					_stream.disposeLocalData(false);
			}

			return _vertexBuffer;
		}

		public function dispose() : void
		{
			if (_vertexBuffer)
			{
				_vertexBuffer.dispose();
				_vertexBuffer = null;
			}

			_disposed = true;
			_stream = null;
			_update = false;
			_numVertices = 0;
		}
	}
}

package aerys.minko.render.resource
{
	import aerys.minko.ns.minko_stream;
	import aerys.minko.render.geometry.stream.IVertexStream;
	import aerys.minko.render.geometry.stream.StreamUsage;
	import aerys.minko.render.geometry.stream.VertexStream;
	import aerys.minko.type.Signal;

	import flash.display3D.Context3D;
	import flash.display3D.VertexBuffer3D;
	import flash.utils.ByteArray;

	/**
	 * VertexBuffer3DResource objects handle vertex buffers allocation
	 * and disposal using the Stage3D API.
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public final class VertexBuffer3DResource implements IResource
	{
		use namespace minko_stream;

		private var _stream			: VertexStream		= null;
		private var _update			: Boolean			= true;
		private var _lengthChanged	: Boolean			= true;
		private var _vertexBuffer	: VertexBuffer3D	= null;
		private var _numVertices	: uint				= 0;

		private var _disposed		: Boolean			= false;

		private var _uploaded		: Signal			= new Signal('VertexBuffer3DRessource.uploaded');

		public function get uploaded() : Signal
		{
			return _uploaded;
		}

		public function get numVertices() : uint
		{
			return _numVertices;
		}

		public function VertexBuffer3DResource(source : VertexStream)
		{
			_stream = source;
			_stream.changed.add(vertexStreamChangedHandler);
		}

		private function vertexStreamChangedHandler(vertexStream : VertexStream) : void
		{
			_update = true;
			_lengthChanged = vertexStream.numVertices != _numVertices;
		}

		public function getVertexBuffer3D(context : Context3DResource) : VertexBuffer3D
		{
			var update	: Boolean	= _update;

			if (_disposed)
				throw new Error('Unable to render a disposed buffer.');

			if (_lengthChanged)
			{
				_lengthChanged = false;
				_numVertices = _stream.numVertices;

				if (_vertexBuffer)
					_vertexBuffer.dispose();

				_vertexBuffer = context.createVertexBuffer(
					_numVertices,
					_stream.format.numBytesPerVertex >>> 2
				);

				update = true;
			}

			if (_vertexBuffer != null && update)
			{
				_vertexBuffer.uploadFromByteArray(_stream._data, 0, 0, _numVertices);
				_uploaded.execute(this);

				_update = false;

				if (!(_stream.usage & StreamUsage.READ) || _stream._localDispose)
					_stream.disposeLocalData(false);
			}

			return _vertexBuffer;
		}

		public function dispose() : void
		{
			if (_vertexBuffer)
			{
				_vertexBuffer.dispose();
				_vertexBuffer = null;
			}

			_disposed = true;
			_stream = null;
			_update = false;
			_numVertices = 0;
		}
	}
}

reorganize imports in VertexBuffer3DResource


package dolly {

import dolly.core.dolly_internal;
import dolly.core.errors.CloningError;
import dolly.core.metadata.MetadataName;

import org.as3commons.reflect.Accessor;
import org.as3commons.reflect.AccessorAccess;
import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;

use namespace dolly_internal;

public class Cloner {

	private static function isTypeCloneable(type:Type):Boolean {
		return type.hasMetadata(MetadataName.CLONEABLE);
	}

	dolly_internal static function findAllWritableFieldsForType(type:Type):Vector.<Field> {
		const result:Vector.<Field> = new Vector.<Field>();

		for each(var field:Field in type.fields) {
			if (field.isStatic) {
				continue;
			}

			if (!(field is Accessor) || (field as Accessor).access == AccessorAccess.READ_WRITE) {
				result.push(field);
			}
		}

		return result;
	}

	public static function clone(source:*):* {
		const type:Type = Type.forInstance(source);

		if (!isTypeCloneable(type)) {
			throw new CloningError(
					CloningError.CLASS_IS_NOT_CLONEABLE_MESSAGE,
					CloningError.CLASS_IS_NOT_CLONEABLE_CODE
			);
		}

		const clone:* = new (type.clazz)();

		// Find all public writable fields in a hierarchy of a source object
		// and assign their values to a clone object.
		const fieldsToClone:Vector.<Field> = findAllWritableFieldsForType(type);
		var name:String;
		for each(var field:Field in fieldsToClone) {
			name = field.name;
			clone[name] = source[name];
		}

		return clone;
	}
}
}

package dolly {

import dolly.core.dolly_internal;
import dolly.core.errors.CloningError;
import dolly.core.metadata.MetadataName;

import org.as3commons.reflect.Accessor;
import org.as3commons.reflect.AccessorAccess;
import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;

use namespace dolly_internal;

public class Cloner {

	private static function isTypeCloneable(type:Type):Boolean {
		return type.hasMetadata(MetadataName.CLONEABLE);
	}

	dolly_internal static function findAllWritableFieldsForType(type:Type):Vector.<Field> {
		const result:Vector.<Field> = new Vector.<Field>();

		for each(var field:Field in type.properties) {
			if (!(field is Accessor) || (field as Accessor).access == AccessorAccess.READ_WRITE) {
				result.push(field);
			}
		}

		return result;
	}

	public static function clone(source:*):* {
		const type:Type = Type.forInstance(source);

		if (!isTypeCloneable(type)) {
			throw new CloningError(
					CloningError.CLASS_IS_NOT_CLONEABLE_MESSAGE,
					CloningError.CLASS_IS_NOT_CLONEABLE_CODE
			);
		}

		const clone:* = new (type.clazz)();

		// Find all public writable fields in a hierarchy of a source object
		// and assign their values to a clone object.
		const fieldsToClone:Vector.<Field> = findAllWritableFieldsForType(type);
		var name:String;
		for each(var field:Field in fieldsToClone) {
			name = field.name;
			clone[name] = source[name];
		}

		return clone;
	}
}
}

Optimize performance for finding of writable fields of Type.


/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 *   Marc Alcaraz <ekameleon@gmail.com>.
 */

package com.google.analytics.campaign
{
    import com.google.analytics.core.Buffer;
    import com.google.analytics.core.OrganicReferrer;
    import com.google.analytics.debug.DebugConfiguration;
    import com.google.analytics.debug.VisualDebugMode;
    import com.google.analytics.utils.Protocols;
    import com.google.analytics.utils.URL;
    import com.google.analytics.utils.Variables;
    import com.google.analytics.v4.Configuration;

    /**
     * The CampaignManager class.
     */
    public class CampaignManager
    {
        private var _config:Configuration;
        private var _debug:DebugConfiguration;
        private var _buffer:Buffer;

        private var _domainHash:Number;
        private var _referrer:String;
        private var _timeStamp:Number;

        /**
         * Delimiter for campaign tracker.
         */
        public static const trackingDelimiter:String = "|";

        /**
         * Creates a new CampaignManager instance.
         */
        public function CampaignManager( config:Configuration, debug:DebugConfiguration, buffer:Buffer,
                                         domainHash:Number, referrer:String, timeStamp:Number )
        {
            _config     = config;
            _debug      = debug;
            _buffer     = buffer;

            _domainHash = domainHash;
            _referrer   = referrer;
            _timeStamp  = timeStamp;
        }

        /**
         * This method will return true if and only document referrer is invalid.
         * Document referrer is considered to be invalid when it's empty (undefined,
         * empty string, "-", or "0"), or it's not a valid URL (doesn't have protocol)
         *
         * @private
         * @param {String} docRef Document referrer to be evaluated for validity.
         *
         * @return {Boolean} True if and only if document referrer is invalid.
         */
        public static function isInvalidReferrer( referrer:String ):Boolean
        {
            if( (referrer == "") ||
                (referrer == "-") ||
                (referrer == "0") )
            {
                return true;
            }

            if( referrer.indexOf("://") > -1 )
            {
                var url:URL = new URL( referrer );

                if( (url.protocol == Protocols.file) ||
                    (url.protocol == Protocols.none) )
                    {
                    return true;
                    }
            }

            return false;
        }

        /**
         * Checks if the document referrer is from the google custom search engine.
         * @private
         * @return true if the referrer is from google custom search engine.
         */
        public static function isFromGoogleCSE( referrer:String, config:Configuration ):Boolean
        {
            var url:URL = new URL( referrer );

            // verify that the referrer is google cse search query.
            if( url.hostName.indexOf( config.google ) > -1 )
            {
                if( url.search.indexOf( config.googleSearchParam+"=" ) > -1 )
                {
                    // check if this is google custom search engine.
                    if( url.path == "/"+config.googleCsePath )
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        /**
         * Retrieves campaign information.  If linker functionality is allowed, and
         * the cookie parsed from search string is valid (hash matches), then load the
         * __utmz value form search string, and write the value to cookie, then return
         * "".  Otherwise, attempt to retrieve __utmz value from cookie.  Then
         * retrieve campaign information from search string.  If that fails, try
         * organic campaigns next.  If that fails, try referral campaigns next.  If
         * that fails, try direct campaigns next.  If it still fails, return nothing.
         * Finally, determine whether the campaign is duplicated.  If the campaign is
         * not duplicated, then write campaign information to cookie, and indicate
         * there is a new campaign for gif hit.  Else, just indicate this is a
         * repeated click for campaign.
         *
         * @private
         * @param {_gat.GA_Cookie_} inCookie GA_Cookie instance containing cookie
         *     values parsed in from URL (linker).  This value should never be
         *     undefined.
         * @param {Boolean} noSession Indicating whether a session has been
         *     initialized. If __utmb and/or __utmc cookies are not set, then session
         *     has either timed-out or havn't been initialized yet.
         *
         * @return {String} Gif hit key-value pair indicating wether this is a repeated
         *     click, or a brand new campaign for the visitor.
         */
        public function getCampaignInformation( search:String, noSessionInformation:Boolean ):CampaignInfo
        {
            var campInfo:CampaignInfo = new CampaignInfo();
            var campaignTracker:CampaignTracker;
            var duplicateCampaign:Boolean = false;
            var campNoOverride:Boolean = false;
            var responseCount:int = 0;

            /* Allow linker functionality, and cookie is parsed from URL, and the cookie
              hash matches.
            */
            if( _config.allowLinker && _buffer.isGenuine() )
            {
                if( !_buffer.hasUTMZ() )
                {
                    return campInfo;
                }
            }

            // retrieves tracker from search string
            campaignTracker = getTrackerFromSearchString( search );

            if( isValid( campaignTracker ) )
            {
                // check for no override flag in search string
                campNoOverride = hasNoOverride( search );

                // if no override is true, and there is a utmz value, then do nothing now
                if( campNoOverride && !_buffer.hasUTMZ() )
                {
                    return campInfo;
                }
            }

            // Get organic campaign if there is no campaign tracker from search string.
            if( !isValid( campaignTracker ) )
            {
                campaignTracker = getOrganicCampaign();

                //If there is utmz cookie value, and organic keyword is being ignored, do nothing.
                if( !_buffer.hasUTMZ() && isIgnoredKeyword( campaignTracker ) )
                {
                    return campInfo;
                }
            }

            /* Get referral campaign if there is no campaign tracker from search string
               and organic campaign, and either utmb or utmc is missing (no session).
            */
            if( !isValid( campaignTracker ) && noSessionInformation )
            {
                campaignTracker = getReferrerCampaign();

                //If there is utmz cookie value, and referral domain is being ignored, do nothing
                if( !_buffer.hasUTMZ() && isIgnoredReferral( campaignTracker ) )
                {
                    return campInfo;
                }
            }

            /* Get direct campaign if there is no campaign tracker from search string,
              organic campaign, or referral campaign.
            */
            if( !isValid( campaignTracker ) )
            {
                /* Only get direct campaign when there is no utmz cookie value, and there is
                   no session. (utmb or utmc is missing value)
                */
                if( !_buffer.hasUTMZ() && noSessionInformation )
                {
                    campaignTracker = getDirectCampaign();
                }

            }

            //Give up (do nothing) if still cannot get campaign tracker.
            if( !isValid( campaignTracker ) )
            {
                return campInfo;
            }

            //utmz cookie have value, check whether campaign is duplicated.
            if( _buffer.hasUTMZ() && !_buffer.utmz.isEmpty() )
            {
                var oldTracker:CampaignTracker = new CampaignTracker();
                    oldTracker.fromTrackerString( _buffer.utmz.campaignTracking );

                duplicateCampaign = ( oldTracker.toTrackerString() == campaignTracker.toTrackerString() );

                responseCount = _buffer.utmz.responseCount;
            }

            /* Record as new campaign if and only if campaign is not duplicated, or there
              is no session information.
            */
            if( !duplicateCampaign || noSessionInformation )
            {
                var sessionCount:int = _buffer.utma.sessionCount;
                responseCount++;

                // if there is no session number, increment
                if( sessionCount == 0 )
                {
                    sessionCount = 1;
                }

                // construct utmz cookie
                _buffer.utmz.domainHash       = _domainHash;
                _buffer.utmz.campaignCreation = _timeStamp;
                _buffer.utmz.campaignSessions = sessionCount;
                _buffer.utmz.responseCount    = responseCount;
                _buffer.utmz.campaignTracking = campaignTracker.toTrackerString();

                _debug.info( _buffer.utmz.toString(), VisualDebugMode.geek );

                // indicate new campaign
                campInfo = new CampaignInfo( false, true );
            }
            else
            {
                // indicate repeated campaign
                campInfo = new CampaignInfo( false, false );
            }

            return campInfo;
        }

        /**
         * This method returns the organic campaign information.
         * @private
         * @return {_gat.GA_Campaign_.Tracker_} Returns undefined if referrer is not
         * a matching organic campaign source. Otherwise, returns the campaign tracker object.
         */
        public function getOrganicCampaign():CampaignTracker
        {
            var camp:CampaignTracker;

            // if there is no referrer, or referrer is not a valid URL, or the referrer
            // is google custom search engine, return an empty tracker
            if( isInvalidReferrer( _referrer ) || isFromGoogleCSE( _referrer, _config ) )
            {
                return camp;
            }

            var ref:URL = new URL( _referrer );
            var name:String = "";

            if( ref.hostName != "" )
            {
                if( ref.hostName.indexOf( "." ) > -1 )
                {
                    var tmp:Array = ref.hostName.split( "." );

                    switch( tmp.length)
                    {
                        case 2:
                        // case: http://domain.com
                        name = tmp[0];
                        break;

                        case 3:
                        //case: http://www.domain.com
                        name = tmp[1];
                        break;
                    }
                }
            }

            // organic source match
            if( _config.organic.match( name ) )
            {
                var currentOrganicSource:OrganicReferrer = _config.organic.getReferrerByName( name );

                // extract keyword value from query string
                var keyword:String = _config.organic.getKeywordValue( currentOrganicSource, ref.search );

                camp = new CampaignTracker();
                camp.source = currentOrganicSource.engine;
                camp.name   = "(organic)";
                camp.medium = "organic";
                camp.term   = keyword;
            }

            return camp;
        }

        /**
         * This method returns the referral campaign information.
         *
         * @private
         * @return {_gat.GA_Campaign_.Tracker_} Returns nothing if there is no
         *     referrer. Otherwise, return referrer campaign tracker.
         */
        public function getReferrerCampaign():CampaignTracker
        {
            var camp:CampaignTracker;

            // if there is no referrer, or referrer is not a valid URL, or the referrer
            // is google custom search engine, return an empty tracker
            if( isInvalidReferrer( _referrer ) || isFromGoogleCSE( _referrer, _config ) )
            {
                return camp;
            }

            // get host name from referrer
            var ref:URL = new URL( _referrer );
            var hostname:String = ref.hostName;
            var content:String  = ref.path;

            if( hostname.indexOf( "www." ) == 0 )
            {
                hostname = hostname.substr( 4 );
            }

            camp = new CampaignTracker();
            camp.source  = hostname;
            camp.name    = "(referral)";
            camp.medium  = "referral";
            camp.content = content;

            return camp;
        }

        /**
         * Returns the direct campaign tracker string.
         * @private
         * @return {_gat.GA_Campaign_.Tracker_} Direct campaign tracker object.
         */
        public function getDirectCampaign():CampaignTracker
        {
            var camp:CampaignTracker = new CampaignTracker();
                camp.source = "(direct)";
                camp.name   = "(direct)";
                camp.medium = "(none)";

            return camp;
        }

        /**
         * Indicates if the manager has no override with the search value.
         */
        public function hasNoOverride( search:String ):Boolean
        {
            var key:CampaignKey = _config.campaignKey;

            if( search == "" )
            {
                return false;
            }

            var variables:Variables = new Variables( search );
            var value:String           = "";

            if( variables.hasOwnProperty( key.UCNO ) )
            {
                value = variables[ key.UCNO ];

                switch( value )
                {
                    case "1":
                    return true;

                    case "":
                    case "0":
                    default:
                    return false;
                }
            }

            return false;
        }

        /**
         * This method returns true if and only if campaignTracker is a valid organic
         * campaign tracker (utmcmd=organic), and the keyword (utmctr) is contained in
         * the ignore watch list (ORGANIC_IGNORE).
         *
         * @private
         * @param {_gat.GA_Campaign_.Tracker_} campaignTracker Campaign tracker
         *     reference.
         *
         * @return {Boolean} Return true if and only if the campaign tracker is a valid
         *     organic campaign tracker, and the keyword is contained in the ignored
         *     watch list.
         */
        public function isIgnoredKeyword( tracker:CampaignTracker ):Boolean
        {
            // organic campaign, try to match ignored keywords
            if( tracker && (tracker.medium == "organic") )
            {
                return _config.organic.isIgnoredKeyword( tracker.term );
            }

            return false;
        }

        /**
         * This method returns true if and only if campaignTracker is a valid
         * referreal campaign tracker (utmcmd=referral), and the domain (utmcsr) is
         * contained in the ignore watch list (REFERRAL_IGNORE).
         *
         * @private
         * @param {String} campaignTracker String representation of the campaign
         *     tracker.
         *
         * @return {Boolean} Return true if and only if the campaign tracker is a
         *     valid referral campaign tracker, and the domain is contained in the
         *     ignored watch list.
         */
        public function isIgnoredReferral( tracker:CampaignTracker ):Boolean
        {
            // referral campaign, try to match ignored domains
            if( tracker && (tracker.medium == "referral") )
            {
                return _config.organic.isIgnoredReferral( tracker.source );
            }

            return false;
        }

        public function isValid( tracker:CampaignTracker ):Boolean
        {
            if( tracker && tracker.isValid() )
            {
                return true;
            }

            return false;
        }

        /**
        * Retrieves campaign tracker from search string.
        *
        * @param {String} searchString Search string to retrieve campaign tracker from.
        * @return {String} Return campaign tracker retrieved from search string.
        */
        public function getTrackerFromSearchString( search:String ):CampaignTracker
        {
            var organicCampaign:CampaignTracker = getOrganicCampaign();
            var camp:CampaignTracker            = new CampaignTracker();
            var key:CampaignKey                 = _config.campaignKey;

            if( search == "" )
            {
                return camp;
            }

            var variables:Variables = new Variables( search );

            //id
            if( variables.hasOwnProperty( key.UCID ) )
            {
                camp.id = variables[ key.UCID ];
            }

            //source
            if( variables.hasOwnProperty( key.UCSR ) )
            {
                camp.source = variables[ key.UCSR ];
            }

            //click id
            if( variables.hasOwnProperty( key.UGCLID ) )
            {
                camp.clickId = variables[ key.UGCLID ];
            }

            //name
            if( variables.hasOwnProperty( key.UCCN ) )
            {
                camp.name = variables[ key.UCCN ];
            }
            else
            {
                camp.name = "(not set)";
            }

            //medium
            if( variables.hasOwnProperty( key.UCMD ) )
            {
                camp.medium = variables[ key.UCMD ];
            }
            else
            {
                camp.medium = "(not set)";
            }

            //term
            if( variables.hasOwnProperty( key.UCTR ) )
            {
                camp.term = variables[ key.UCTR ];
            }
            else if( organicCampaign && organicCampaign.term != "" )
            {
                camp.term = organicCampaign.term;
            }

            //content
            if( variables.hasOwnProperty( key.UCCT ) )
            {
                camp.content = variables[ key.UCCT ];
            }

            return camp;
        }

    }
}

/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 *   Marc Alcaraz <ekameleon@gmail.com>.
 */

package com.google.analytics.campaign
{
    import com.google.analytics.core.Buffer;
    import com.google.analytics.core.OrganicReferrer;
    import com.google.analytics.debug.DebugConfiguration;
    import com.google.analytics.debug.VisualDebugMode;
    import com.google.analytics.utils.Variables;
    import com.google.analytics.v4.Configuration;

    import core.uri;

    /**
     * The CampaignManager class.
     */
    public class CampaignManager
    {
        private var _config:Configuration;
        private var _debug:DebugConfiguration;
        private var _buffer:Buffer;

        private var _domainHash:Number;
        private var _referrer:String;
        private var _timeStamp:Number;

        /**
         * Delimiter for campaign tracker.
         */
        public static const trackingDelimiter:String = "|";

        /**
         * Creates a new CampaignManager instance.
         */
        public function CampaignManager( config:Configuration, debug:DebugConfiguration, buffer:Buffer,
                                         domainHash:Number, referrer:String, timeStamp:Number )
        {
            _config     = config;
            _debug      = debug;
            _buffer     = buffer;

            _domainHash = domainHash;
            _referrer   = referrer;
            _timeStamp  = timeStamp;
        }

        /**
         * This method will return true if and only document referrer is invalid.
         * Document referrer is considered to be invalid when it's empty (undefined,
         * empty string, "-", or "0"), or it's not a valid URL (doesn't have protocol)
         *
         * @private
         * @param {String} docRef Document referrer to be evaluated for validity.
         *
         * @return {Boolean} True if and only if document referrer is invalid.
         */
        public static function isInvalidReferrer( referrer:String ):Boolean
        {
            if( (referrer == "") ||
                (referrer == "-") ||
                (referrer == "0") )
            {
                return true;
            }

            var url:uri = new uri( referrer );

            if( (url.scheme == "file") ||
                (url.scheme == "") )
            {
                return true;
            }

            return false;
        }

        /**
         * Checks if the document referrer is from the google custom search engine.
         * @private
         * @return true if the referrer is from google custom search engine.
         */
        public static function isFromGoogleCSE( referrer:String, config:Configuration ):Boolean
        {
            var url:uri = new uri( referrer );

            if( url.host.indexOf( config.google ) > -1 )
            {
                if( (url.path == "/"+config.googleCsePath ) &&
                    (url.query.indexOf( config.googleSearchParam+"=" ) > -1) )
                {
                    return true;
                }
            }

            return false;
        }

        /**
         * Retrieves campaign information.  If linker functionality is allowed, and
         * the cookie parsed from search string is valid (hash matches), then load the
         * __utmz value form search string, and write the value to cookie, then return
         * "".  Otherwise, attempt to retrieve __utmz value from cookie.  Then
         * retrieve campaign information from search string.  If that fails, try
         * organic campaigns next.  If that fails, try referral campaigns next.  If
         * that fails, try direct campaigns next.  If it still fails, return nothing.
         * Finally, determine whether the campaign is duplicated.  If the campaign is
         * not duplicated, then write campaign information to cookie, and indicate
         * there is a new campaign for gif hit.  Else, just indicate this is a
         * repeated click for campaign.
         *
         * @private
         * @param {_gat.GA_Cookie_} inCookie GA_Cookie instance containing cookie
         *     values parsed in from URL (linker).  This value should never be
         *     undefined.
         * @param {Boolean} noSession Indicating whether a session has been
         *     initialized. If __utmb and/or __utmc cookies are not set, then session
         *     has either timed-out or havn't been initialized yet.
         *
         * @return {String} Gif hit key-value pair indicating wether this is a repeated
         *     click, or a brand new campaign for the visitor.
         */
        public function getCampaignInformation( search:String, noSessionInformation:Boolean ):CampaignInfo
        {
            var campInfo:CampaignInfo = new CampaignInfo();
            var campaignTracker:CampaignTracker;
            var duplicateCampaign:Boolean = false;
            var campNoOverride:Boolean = false;
            var responseCount:int = 0;

            /* Allow linker functionality, and cookie is parsed from URL, and the cookie
              hash matches.
            */
            if( _config.allowLinker && _buffer.isGenuine() )
            {
                if( !_buffer.hasUTMZ() )
                {
                    return campInfo;
                }
            }

            // retrieves tracker from search string
            campaignTracker = getTrackerFromSearchString( search );

            if( isValid( campaignTracker ) )
            {
                // check for no override flag in search string
                campNoOverride = hasNoOverride( search );

                // if no override is true, and there is a utmz value, then do nothing now
                if( campNoOverride && !_buffer.hasUTMZ() )
                {
                    return campInfo;
                }
            }

            // Get organic campaign if there is no campaign tracker from search string.
            if( !isValid( campaignTracker ) )
            {
                campaignTracker = getOrganicCampaign();

                //If there is utmz cookie value, and organic keyword is being ignored, do nothing.
                if( !_buffer.hasUTMZ() && isIgnoredKeyword( campaignTracker ) )
                {
                    return campInfo;
                }
            }

            /* Get referral campaign if there is no campaign tracker from search string
               and organic campaign, and either utmb or utmc is missing (no session).
            */
            if( !isValid( campaignTracker ) && noSessionInformation )
            {
                campaignTracker = getReferrerCampaign();

                //If there is utmz cookie value, and referral domain is being ignored, do nothing
                if( !_buffer.hasUTMZ() && isIgnoredReferral( campaignTracker ) )
                {
                    return campInfo;
                }
            }

            /* Get direct campaign if there is no campaign tracker from search string,
              organic campaign, or referral campaign.
            */
            if( !isValid( campaignTracker ) )
            {
                /* Only get direct campaign when there is no utmz cookie value, and there is
                   no session. (utmb or utmc is missing value)
                */
                if( !_buffer.hasUTMZ() && noSessionInformation )
                {
                    campaignTracker = getDirectCampaign();
                }

            }

            //Give up (do nothing) if still cannot get campaign tracker.
            if( !isValid( campaignTracker ) )
            {
                return campInfo;
            }

            //utmz cookie have value, check whether campaign is duplicated.
            if( _buffer.hasUTMZ() && !_buffer.utmz.isEmpty() )
            {
                var oldTracker:CampaignTracker = new CampaignTracker();
                    oldTracker.fromTrackerString( _buffer.utmz.campaignTracking );

                duplicateCampaign = ( oldTracker.toTrackerString() == campaignTracker.toTrackerString() );

                responseCount = _buffer.utmz.responseCount;
            }

            /* Record as new campaign if and only if campaign is not duplicated, or there
              is no session information.
            */
            if( !duplicateCampaign || noSessionInformation )
            {
                var sessionCount:int = _buffer.utma.sessionCount;
                responseCount++;

                // if there is no session number, increment
                if( sessionCount == 0 )
                {
                    sessionCount = 1;
                }

                // construct utmz cookie
                _buffer.utmz.domainHash       = _domainHash;
                _buffer.utmz.campaignCreation = _timeStamp;
                _buffer.utmz.campaignSessions = sessionCount;
                _buffer.utmz.responseCount    = responseCount;
                _buffer.utmz.campaignTracking = campaignTracker.toTrackerString();

                _debug.info( _buffer.utmz.toString(), VisualDebugMode.geek );

                // indicate new campaign
                campInfo = new CampaignInfo( false, true );
            }
            else
            {
                // indicate repeated campaign
                campInfo = new CampaignInfo( false, false );
            }

            return campInfo;
        }

        /**
         * This method returns the organic campaign information.
         * @private
         * @return {_gat.GA_Campaign_.Tracker_} Returns undefined if referrer is not
         * a matching organic campaign source. Otherwise, returns the campaign tracker object.
         */
        public function getOrganicCampaign():CampaignTracker
        {
            var camp:CampaignTracker;

            // if there is no referrer, or referrer is not a valid URL, or the referrer
            // is google custom search engine, return an empty tracker
            if( isInvalidReferrer( _referrer ) || isFromGoogleCSE( _referrer, _config ) )
            {
                return camp;
            }

            var ref:uri = new uri( _referrer );
            var name:String;

            if( (ref.host != "") && (ref.host.indexOf(".") > -1) )
            {
                var tmp:Array = ref.host.split( "." );

                switch( tmp.length )
                {
                    case 2:
                    name = tmp[0];
                    break;

                    case 3:
                    name = tmp[1];
                }
            }

            // organic source match
            if( _config.organic.match( name ) )
            {
                var currentOrganicSource:OrganicReferrer = _config.organic.getReferrerByName( name );

                // extract keyword value from query string
                var keyword:String = _config.organic.getKeywordValue( currentOrganicSource, ref.query );

                camp = new CampaignTracker();
                camp.source = currentOrganicSource.engine;
                camp.name   = "(organic)";
                camp.medium = "organic";
                camp.term   = keyword;
            }

            return camp;
        }

        /**
         * This method returns the referral campaign information.
         *
         * @private
         * @return {_gat.GA_Campaign_.Tracker_} Returns nothing if there is no
         *     referrer. Otherwise, return referrer campaign tracker.
         */
        public function getReferrerCampaign():CampaignTracker
        {
            var camp:CampaignTracker;

            // if there is no referrer, or referrer is not a valid URL, or the referrer
            // is google custom search engine, return an empty tracker
            if( isInvalidReferrer( _referrer ) || isFromGoogleCSE( _referrer, _config ) )
            {
                return camp;
            }

            // get host name from referrer
            var ref:uri = new uri( _referrer );
            var hostname:String = ref.host;
            var content:String  = ref.path;

            if( content == "" ) { content = "/"; } //fix empty path

            if( hostname.indexOf( "www." ) == 0 )
            {
                hostname = hostname.substr( 4 );
            }

            camp = new CampaignTracker();
            camp.source  = hostname;
            camp.name    = "(referral)";
            camp.medium  = "referral";
            camp.content = content;

            return camp;
        }

        /**
         * Returns the direct campaign tracker string.
         * @private
         * @return {_gat.GA_Campaign_.Tracker_} Direct campaign tracker object.
         */
        public function getDirectCampaign():CampaignTracker
        {
            var camp:CampaignTracker = new CampaignTracker();
                camp.source = "(direct)";
                camp.name   = "(direct)";
                camp.medium = "(none)";

            return camp;
        }

        /**
         * Indicates if the manager has no override with the search value.
         */
        public function hasNoOverride( search:String ):Boolean
        {
            var key:CampaignKey = _config.campaignKey;

            if( search == "" )
            {
                return false;
            }

            var variables:Variables = new Variables( search );
            var value:String           = "";

            if( variables.hasOwnProperty( key.UCNO ) )
            {
                value = variables[ key.UCNO ];

                switch( value )
                {
                    case "1":
                    return true;

                    case "":
                    case "0":
                    default:
                    return false;
                }
            }

            return false;
        }

        /**
         * This method returns true if and only if campaignTracker is a valid organic
         * campaign tracker (utmcmd=organic), and the keyword (utmctr) is contained in
         * the ignore watch list (ORGANIC_IGNORE).
         *
         * @private
         * @param {_gat.GA_Campaign_.Tracker_} campaignTracker Campaign tracker
         *     reference.
         *
         * @return {Boolean} Return true if and only if the campaign tracker is a valid
         *     organic campaign tracker, and the keyword is contained in the ignored
         *     watch list.
         */
        public function isIgnoredKeyword( tracker:CampaignTracker ):Boolean
        {
            // organic campaign, try to match ignored keywords
            if( tracker && (tracker.medium == "organic") )
            {
                return _config.organic.isIgnoredKeyword( tracker.term );
            }

            return false;
        }

        /**
         * This method returns true if and only if campaignTracker is a valid
         * referreal campaign tracker (utmcmd=referral), and the domain (utmcsr) is
         * contained in the ignore watch list (REFERRAL_IGNORE).
         *
         * @private
         * @param {String} campaignTracker String representation of the campaign
         *     tracker.
         *
         * @return {Boolean} Return true if and only if the campaign tracker is a
         *     valid referral campaign tracker, and the domain is contained in the
         *     ignored watch list.
         */
        public function isIgnoredReferral( tracker:CampaignTracker ):Boolean
        {
            // referral campaign, try to match ignored domains
            if( tracker && (tracker.medium == "referral") )
            {
                return _config.organic.isIgnoredReferral( tracker.source );
            }

            return false;
        }

        public function isValid( tracker:CampaignTracker ):Boolean
        {
            if( tracker && tracker.isValid() )
            {
                return true;
            }

            return false;
        }

        /**
        * Retrieves campaign tracker from search string.
        *
        * @param {String} searchString Search string to retrieve campaign tracker from.
        * @return {String} Return campaign tracker retrieved from search string.
        */
        public function getTrackerFromSearchString( search:String ):CampaignTracker
        {
            var organicCampaign:CampaignTracker = getOrganicCampaign();
            var camp:CampaignTracker            = new CampaignTracker();
            var key:CampaignKey                 = _config.campaignKey;

            if( search == "" )
            {
                return camp;
            }

            var variables:Variables = new Variables( search );

            //id
            if( variables.hasOwnProperty( key.UCID ) )
            {
                camp.id = variables[ key.UCID ];
            }

            //source
            if( variables.hasOwnProperty( key.UCSR ) )
            {
                camp.source = variables[ key.UCSR ];
            }

            //click id
            if( variables.hasOwnProperty( key.UGCLID ) )
            {
                camp.clickId = variables[ key.UGCLID ];
            }

            //name
            if( variables.hasOwnProperty( key.UCCN ) )
            {
                camp.name = variables[ key.UCCN ];
            }
            else
            {
                camp.name = "(not set)";
            }

            //medium
            if( variables.hasOwnProperty( key.UCMD ) )
            {
                camp.medium = variables[ key.UCMD ];
            }
            else
            {
                camp.medium = "(not set)";
            }

            //term
            if( variables.hasOwnProperty( key.UCTR ) )
            {
                camp.term = variables[ key.UCTR ];
            }
            else if( organicCampaign && organicCampaign.term != "" )
            {
                camp.term = organicCampaign.term;
            }

            //content
            if( variables.hasOwnProperty( key.UCCT ) )
            {
                camp.content = variables[ key.UCCT ];
            }

            return camp;
        }

    }
}

replace URL class by core.uri

replace URL class by core.uri


/**
 * User: booster
 * Date: 05/03/15
 * Time: 16:38
 */
package tire.ui {
import feathers.controls.Button;
import feathers.controls.Header;
import feathers.controls.List;
import feathers.controls.PanelScreen;
import feathers.controls.Slider;
import feathers.controls.ToggleSwitch;
import feathers.controls.renderers.DefaultListItemRenderer;
import feathers.controls.renderers.IListItemRenderer;
import feathers.data.ListCollection;
import feathers.layout.AnchorLayout;
import feathers.layout.AnchorLayoutData;

import starling.display.DisplayObject;
import starling.events.Event;

import tire.TirePhysics;

public class WheelDataScreen extends PanelScreen {
    private var _wheelMassSlider:Slider;
    private var _wheelRadiusSlider:Slider;
    private var _wheelInertiaLocked:ToggleSwitch;
    private var _wheelInertiaSlider:Slider;
    private var _loadMassSlider:Slider;
    private var _frontalAreaSlider:Slider;
    private var _maxAccTorqueSlider:Slider;
    private var _maxBrakingTorqueSlider:Slider;

    private var _list:List;

    private var _tirePhysics:TirePhysics;

    public function get tirePhysics():TirePhysics { return _tirePhysics; }
    public function set tirePhysics(value:TirePhysics):void { _tirePhysics = value; }

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

        layout = new AnchorLayout();

        title = "Wheel settings";

        _wheelMassSlider = new Slider();
        _wheelMassSlider.minimum = 5;
        _wheelMassSlider.maximum = 30;
        _wheelMassSlider.step = 0.1;
        _wheelMassSlider.value = _tirePhysics.wheelMass;
        _wheelMassSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.wheelMass = _wheelMassSlider.value;

            if(_wheelInertiaLocked.isSelected)
                _tirePhysics.validateInertia();
        });
        UiHelper.setupSlider(_wheelMassSlider);

        _wheelRadiusSlider = new Slider();
        _wheelRadiusSlider.minimum = 0.1;
        _wheelRadiusSlider.maximum = 5;
        _wheelRadiusSlider.step = 0.1;
        _wheelRadiusSlider.value = tirePhysics.wheelRadius;
        _wheelRadiusSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.wheelRadius = _wheelRadiusSlider.value;

            if(_wheelInertiaLocked.isSelected)
                _tirePhysics.validateInertia();
        });
        UiHelper.setupSlider(_wheelRadiusSlider);

        _wheelInertiaSlider = new SecretSlider();
        _wheelInertiaSlider.minimum = 0.1;
        _wheelInertiaSlider.maximum = 50;
        _wheelInertiaSlider.step = 0.1;
        _wheelInertiaSlider.value = 20;
        _wheelInertiaSlider.isEnabled = _tirePhysics.wheelInertiaLocked;
        _wheelInertiaSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.wheelInertia = _wheelInertiaSlider.value;
        });
        UiHelper.setupSlider(_wheelInertiaSlider);

        _wheelInertiaLocked = new ToggleSwitch();
        _wheelInertiaLocked.onText = "Yes";
        _wheelInertiaLocked.offText = "No";
        _wheelInertiaLocked.isSelected = _tirePhysics.wheelInertiaLocked;
        _wheelInertiaLocked.addEventListener(Event.CHANGE, function (e:Event):void {
            var sliderItem:Object = null, sliderIndex:int = -1;

            var count:int = _list.dataProvider.length;
            for(var i:int = 0; i < count; ++i) {
                var item:Object = _list.dataProvider.getItemAt(i);

                if(item.accessory != _wheelInertiaSlider)
                    continue;

                sliderItem = item;
                sliderIndex = i;
                break;
            }

            _tirePhysics.wheelInertiaLocked = _wheelInertiaLocked.isSelected;

            if(! _tirePhysics.wheelInertiaLocked) {
                sliderItem.enabled = false;
                _tirePhysics.validateInertia();
            }
            else {
                sliderItem.enabled = true;
                _tirePhysics.wheelInertia = _wheelInertiaSlider.value;
            }

            _list.dataProvider.updateItemAt(sliderIndex);
        });

        _loadMassSlider = new Slider();
        _loadMassSlider.minimum = 10;
        _loadMassSlider.maximum = 1000;
        _loadMassSlider.step = 10;
        _loadMassSlider.value = _tirePhysics.carMass;
        _loadMassSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.carMass = _loadMassSlider.value;
        });
        UiHelper.setupSlider(_loadMassSlider);

        _frontalAreaSlider = new Slider();
        _frontalAreaSlider.minimum = 0.5;
        _frontalAreaSlider.maximum = 5;
        _frontalAreaSlider.step = 0.1;
        _frontalAreaSlider.value = _tirePhysics.frontalArea;
        _frontalAreaSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.frontalArea = _frontalAreaSlider.value;
        });
        UiHelper.setupSlider(_frontalAreaSlider);

        _maxAccTorqueSlider = new Slider();
        _maxAccTorqueSlider.minimum = 100;
        _maxAccTorqueSlider.maximum = 2000;
        _maxAccTorqueSlider.step = 50;
        _maxAccTorqueSlider.value = _tirePhysics.wheelTorque;
        _maxAccTorqueSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.wheelTorque = _maxAccTorqueSlider.value;
        });
        UiHelper.setupSlider(_maxAccTorqueSlider);

        _maxBrakingTorqueSlider = new Slider();
        _maxBrakingTorqueSlider.minimum = 300;
        _maxBrakingTorqueSlider.maximum = 6000;
        _maxBrakingTorqueSlider.step = 50;
        _maxBrakingTorqueSlider.value = _tirePhysics.brakeTorque;
        _maxBrakingTorqueSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.brakeTorque = _maxBrakingTorqueSlider.value;
        });
        UiHelper.setupSlider(_maxBrakingTorqueSlider);

        _list = new List();
        _list.isSelectable = false;
        _list.dataProvider = new ListCollection([
            { label : "Wheel mass", accessory : _wheelMassSlider },
            { label : "Wheel radius", accessory : _wheelRadiusSlider },
            { label : "Wheel inertia locked", accessory : _wheelInertiaLocked},
            { label : "Wheel inertia", accessory : _wheelInertiaSlider, enabled : _tirePhysics.wheelInertiaLocked},
            { label : "Load mass", accessory : _loadMassSlider},
            { label : "Frontal area", accessory : _frontalAreaSlider},
            { label : "Acc. torque", accessory : _maxAccTorqueSlider},
            { label : "Braking torque", accessory : _maxBrakingTorqueSlider},
        ]);
        _list.layoutData = new AnchorLayoutData(0, 0, 0, 0);
        _list.clipContent = false;
        _list.autoHideBackground = true;
        _list.itemRendererFactory = function():IListItemRenderer {
            var renderer:DefaultListItemRenderer = new DefaultListItemRenderer();
            renderer.itemHasEnabled = true;

            return renderer;
        };
//        list.addEventListener(FeathersEventType.CREATION_COMPLETE, function(e:Event):void {
//            _wheelInertiaSlider.isEnabled = _tirePhysics.wheelInertiaLocked;
//        });
        addChild(_list);

        headerFactory = customHeaderFactory;

        backButtonHandler = function ():void {
            _tirePhysics.save();
            dispatchEventWith(Event.COMPLETE);
        };
    }

    private function customHeaderFactory():Header {
        var header:Header = new Header();
        var backButton:Button = new Button();
        backButton.styleNameList.add(Button.ALTERNATE_NAME_BACK_BUTTON);
        backButton.label = "Back";
        backButton.addEventListener(Event.TRIGGERED, function(e:Event):void {
            _tirePhysics.save();
            dispatchEventWith(Event.COMPLETE);
        });
        header.leftItems = new <DisplayObject>[backButton];
        return header;
    }
}
}

import feathers.controls.Slider;

class SecretSlider extends Slider {

    override public function set isEnabled(value:Boolean):void {
        super.isEnabled = value;
    }

    override public function get isEnabled():Boolean {
        return super.isEnabled;
    }
}

/**
 * User: booster
 * Date: 05/03/15
 * Time: 16:38
 */
package tire.ui {
import feathers.controls.Button;
import feathers.controls.Header;
import feathers.controls.List;
import feathers.controls.PanelScreen;
import feathers.controls.Slider;
import feathers.controls.ToggleSwitch;
import feathers.controls.renderers.DefaultListItemRenderer;
import feathers.controls.renderers.IListItemRenderer;
import feathers.data.ListCollection;
import feathers.layout.AnchorLayout;
import feathers.layout.AnchorLayoutData;

import starling.display.DisplayObject;
import starling.events.Event;

import tire.TirePhysics;

public class WheelDataScreen extends PanelScreen {
    private var _wheelMassSlider:Slider;
    private var _wheelRadiusSlider:Slider;
    private var _wheelInertiaLocked:ToggleSwitch;
    private var _wheelInertiaSlider:Slider;
    private var _loadMassSlider:Slider;
    private var _frontalAreaSlider:Slider;
    private var _maxAccTorqueSlider:Slider;
    private var _maxBrakingTorqueSlider:Slider;

    private var _list:List;

    private var _tirePhysics:TirePhysics;

    public function get tirePhysics():TirePhysics { return _tirePhysics; }
    public function set tirePhysics(value:TirePhysics):void { _tirePhysics = value; }

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

        layout = new AnchorLayout();

        title = "Wheel settings";

        _wheelMassSlider = new Slider();
        _wheelMassSlider.minimum = 5;
        _wheelMassSlider.maximum = 30;
        _wheelMassSlider.step = 0.1;
        _wheelMassSlider.value = _tirePhysics.wheelMass;
        _wheelMassSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.wheelMass = _wheelMassSlider.value;

            if(_wheelInertiaLocked.isSelected)
                _tirePhysics.validateInertia();
        });
        UiHelper.setupSlider(_wheelMassSlider);

        _wheelRadiusSlider = new Slider();
        _wheelRadiusSlider.minimum = 0.1;
        _wheelRadiusSlider.maximum = 5;
        _wheelRadiusSlider.step = 0.1;
        _wheelRadiusSlider.value = tirePhysics.wheelRadius;
        _wheelRadiusSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.wheelRadius = _wheelRadiusSlider.value;

            if(_wheelInertiaLocked.isSelected)
                _tirePhysics.validateInertia();
        });
        UiHelper.setupSlider(_wheelRadiusSlider);

        _wheelInertiaSlider = new SecretSlider();
        _wheelInertiaSlider.minimum = 0.1;
        _wheelInertiaSlider.maximum = 50;
        _wheelInertiaSlider.step = 0.1;
        _wheelInertiaSlider.value = tirePhysics.wheelInertia;
        _wheelInertiaSlider.isEnabled = _tirePhysics.wheelInertiaLocked;
        _wheelInertiaSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.wheelInertia = _wheelInertiaSlider.value;
        });
        UiHelper.setupSlider(_wheelInertiaSlider);

        _wheelInertiaLocked = new ToggleSwitch();
        _wheelInertiaLocked.onText = "Yes";
        _wheelInertiaLocked.offText = "No";
        _wheelInertiaLocked.isSelected = _tirePhysics.wheelInertiaLocked;
        _wheelInertiaLocked.addEventListener(Event.CHANGE, function (e:Event):void {
            var sliderItem:Object = null, sliderIndex:int = -1;

            var count:int = _list.dataProvider.length;
            for(var i:int = 0; i < count; ++i) {
                var item:Object = _list.dataProvider.getItemAt(i);

                if(item.accessory != _wheelInertiaSlider)
                    continue;

                sliderItem = item;
                sliderIndex = i;
                break;
            }

            _tirePhysics.wheelInertiaLocked = _wheelInertiaLocked.isSelected;

            if(! _tirePhysics.wheelInertiaLocked) {
                sliderItem.enabled = false;
                _tirePhysics.validateInertia();
            }
            else {
                sliderItem.enabled = true;
                _tirePhysics.wheelInertia = _wheelInertiaSlider.value;
            }

            _list.dataProvider.updateItemAt(sliderIndex);
        });

        _loadMassSlider = new Slider();
        _loadMassSlider.minimum = 10;
        _loadMassSlider.maximum = 1000;
        _loadMassSlider.step = 10;
        _loadMassSlider.value = _tirePhysics.carMass;
        _loadMassSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.carMass = _loadMassSlider.value;
        });
        UiHelper.setupSlider(_loadMassSlider);

        _frontalAreaSlider = new Slider();
        _frontalAreaSlider.minimum = 0.5;
        _frontalAreaSlider.maximum = 5;
        _frontalAreaSlider.step = 0.1;
        _frontalAreaSlider.value = _tirePhysics.frontalArea;
        _frontalAreaSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.frontalArea = _frontalAreaSlider.value;
        });
        UiHelper.setupSlider(_frontalAreaSlider);

        _maxAccTorqueSlider = new Slider();
        _maxAccTorqueSlider.minimum = 100;
        _maxAccTorqueSlider.maximum = 2000;
        _maxAccTorqueSlider.step = 50;
        _maxAccTorqueSlider.value = _tirePhysics.wheelTorque;
        _maxAccTorqueSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.wheelTorque = _maxAccTorqueSlider.value;
        });
        UiHelper.setupSlider(_maxAccTorqueSlider);

        _maxBrakingTorqueSlider = new Slider();
        _maxBrakingTorqueSlider.minimum = 300;
        _maxBrakingTorqueSlider.maximum = 6000;
        _maxBrakingTorqueSlider.step = 50;
        _maxBrakingTorqueSlider.value = _tirePhysics.brakeTorque;
        _maxBrakingTorqueSlider.addEventListener(Event.CHANGE, function (e:Event):void {
            _tirePhysics.brakeTorque = _maxBrakingTorqueSlider.value;
        });
        UiHelper.setupSlider(_maxBrakingTorqueSlider);

        _list = new List();
        _list.isSelectable = false;
        _list.dataProvider = new ListCollection([
            { label : "Wheel mass", accessory : _wheelMassSlider },
            { label : "Wheel radius", accessory : _wheelRadiusSlider },
            { label : "Wheel inertia locked", accessory : _wheelInertiaLocked},
            { label : "Wheel inertia", accessory : _wheelInertiaSlider, enabled : _tirePhysics.wheelInertiaLocked},
            { label : "Load mass", accessory : _loadMassSlider},
            { label : "Frontal area", accessory : _frontalAreaSlider},
            { label : "Acc. torque", accessory : _maxAccTorqueSlider},
            { label : "Braking torque", accessory : _maxBrakingTorqueSlider},
        ]);
        _list.layoutData = new AnchorLayoutData(0, 0, 0, 0);
        _list.clipContent = false;
        _list.autoHideBackground = true;
        _list.itemRendererFactory = function():IListItemRenderer {
            var renderer:DefaultListItemRenderer = new DefaultListItemRenderer();
            renderer.itemHasEnabled = true;

            return renderer;
        };
//        list.addEventListener(FeathersEventType.CREATION_COMPLETE, function(e:Event):void {
//            _wheelInertiaSlider.isEnabled = _tirePhysics.wheelInertiaLocked;
//        });
        addChild(_list);

        headerFactory = customHeaderFactory;

        backButtonHandler = function ():void {
            _tirePhysics.save();
            dispatchEventWith(Event.COMPLETE);
        };
    }

    private function customHeaderFactory():Header {
        var header:Header = new Header();
        var backButton:Button = new Button();
        backButton.styleNameList.add(Button.ALTERNATE_NAME_BACK_BUTTON);
        backButton.label = "Back";
        backButton.addEventListener(Event.TRIGGERED, function(e:Event):void {
            _tirePhysics.save();
            dispatchEventWith(Event.COMPLETE);
        });
        header.leftItems = new <DisplayObject>[backButton];
        return header;
    }
}
}

import feathers.controls.Slider;

class SecretSlider extends Slider {

    override public function set isEnabled(value:Boolean):void {
        super.isEnabled = value;
    }

    override public function get isEnabled():Boolean {
        return super.isEnabled;
    }
}

Initialize slider with current inertia instead of constant