/**
  * LzMouseKernel.as
  *
  * @copyright Copyright 2001-2010 Laszlo Systems, Inc.  All Rights Reserved.
  *            Use is subject to license terms.
  *
  * @topic Kernel
  * @subtopic swf9
  */

// Receives mouse events from the runtime
class LzMouseKernel  {
    #passthrough (toplevel:true) {
    import flash.display.Sprite;
    import flash.display.DisplayObject;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.ui.*;
    import flash.utils.getDefinitionByName;
    }#

    //////////////////
    // MOUSE EVENTS //
    //////////////////

    // sends mouse events to the callback
    static function handleMouseEvent (view:*, eventname:String) :void {
        if (__callback) __scope[__callback](eventname, view);
        //Debug.write('LzMouseKernel event', eventname);
    }

    static var __callback:String = null;
    static var __scope:* = null;
    static var __lastMouseDown:LzSprite = null;
    static var __mouseLeft:Boolean = false;
    static var __listeneradded:Boolean = false;

    /**
     * Shows or hides the hand cursor for all clickable views.
     */
    static var showhandcursor:Boolean = true;

    static function setCallback (scope:*, funcname:String) :void {
        __scope = scope;
        __callback = funcname;
        if (__listeneradded == false) {
            /* TODO [hqm 2008-01] Do we want to do anything with other
            * events, like click?
            stage.addEventListener(MouseEvent.CLICK, reportClick);
            */

            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_MOVE, __mouseHandler);
            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_UP,   __mouseHandler);
            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_DOWN, __mouseHandler);
            // handled by lz.embed.mousewheel for Windows LFCApplication.stage.addEventListener(MouseEvent.MOUSE_WHEEL, __mouseWheelHandler);
            LFCApplication.stage.addEventListener(Event.MOUSE_LEAVE, __mouseLeaveHandler);
            __listeneradded = true;
        }
    }

    // Handles global mouse events
    static function __mouseHandler (event:MouseEvent) :void {
        var eventname:String = 'on' + event.type.toLowerCase();
        if (eventname == 'onmouseup' && __lastMouseDown != null) {
            // call mouseup on the sprite that got the last mouse down
            __lastMouseDown.__globalmouseup(event);
            __lastMouseDown = null;
        } else {
            if (__mouseLeft) {
                __mouseLeft = false;
                // Mouse reentered the app.
                if (event.buttonDown) __mouseUpOutsideHandler();

                if (lz.embed.browser.isFirefox && lz.embed.browser.OS == 'mac' && lz.embed.browser.version < 3.5) {
                    // TODO [hqm 2009-04] LPP-7957 -- this works
                    // around Firefox bug; if you are making a text
                    // selection, and then drag the mouse outside of
                    // the app while the left button is down, and then
                    // release it. When you bring the mouse back into
                    // the app, the selection is stuck dragging
                    // because Flash plugin never gets the mouse up.
                    LFCApplication.stage.focus = null;
                }

                // generate a 'onmouseenter' event
                handleMouseEvent(null, 'onmouseenter');
            }
            handleMouseEvent(null, eventname);
        }
    }

    // sends mouseup and calls __globalmouseup when the mouse goes up outside the app - see LPP-7724
    static function __mouseUpOutsideHandler () :void {
        if (__lastMouseDown != null) {
            var ev:MouseEvent = new MouseEvent('mouseup');
            __lastMouseDown.__globalmouseup(ev);
            __lastMouseDown = null;
        }
    }

    // handles MOUSE_LEAVE event
    static function __mouseLeaveHandler (event:Event = null) :void {
        __mouseLeft = true;
        handleMouseEvent(null, 'onmouseleave');
    }

    static function __mouseWheelHandler (event:MouseEvent) :void {
        lz.Keys.__mousewheelEvent(event.delta);
    }

    //////////////////
    // MOUSE CURSOR //
    //////////////////

    /**
    * Shows or hides the hand cursor for all clickable views.
    * @param Boolean show: true shows the hand cursor for buttons, false hides it
    */
    static function showHandCursor (show:Boolean) :void {
        showhandcursor = show;
        LzSprite.rootSprite.setGlobalHandCursor(show);
    }

    static var __amLocked:Boolean = false;
    static var useBuiltinCursor:Boolean = false;
    static var cursorSprite:Sprite = null;
    static var cursorOffsetX:int = 0;
    static var cursorOffsetY:int = 0;
    static var globalCursorResource:String = null;
    static var lastCursorResource:String = null;

    #passthrough {
        private static var __MouseCursor:Object = null;
        private static function get MouseCursor () :Object {
            if (__MouseCursor == null) {
                __MouseCursor = getDefinitionByName('flash.ui.MouseCursor');
            }
            return __MouseCursor;
        }

        private static var __builtinCursors:Object = null;
        static function get builtinCursors () :Object {
            if (__builtinCursors == null) {
                var cursors:Object = {};
                if ($swf10) {
                    cursors[MouseCursor.ARROW] = true;
                    cursors[MouseCursor.AUTO] = true;
                    cursors[MouseCursor.BUTTON] = true;
                    cursors[MouseCursor.HAND] = true;
                    cursors[MouseCursor.IBEAM] = true;
                }
                __builtinCursors = cursors;
            }
            return __builtinCursors;
        }

        static function get hasGlobalCursor () :Boolean {
            var gcursor:String = globalCursorResource;
            if ($swf10) {
                return ! (gcursor == null || (gcursor == MouseCursor.AUTO && useBuiltinCursor));
            } else {
                return ! (gcursor == null);
            }
        }
    }#

    /**
    * Sets the cursor to a resource
    * @param String what: The resource to use as the cursor.
    */
    static function setCursorGlobal (what:String) :void {
        globalCursorResource = what;
        setCursorLocal(what);
    }

    static function setCursorLocal (what:String) :void {
        if ( __amLocked ) { return; }
        if (what == null) {
            // null is invalid, maybe call restoreCursor()?
            return;
        } else if (lastCursorResource != what) {
            var resourceSprite:DisplayObject = getCursorResource(what);
            if (resourceSprite != null) {
                if (cursorSprite.numChildren > 0) {
                    cursorSprite.removeChildAt(0);
                }
                cursorSprite.addChild( resourceSprite );
                useBuiltinCursor = false;
            } else if (builtinCursors[what] != null) {
                useBuiltinCursor = true;
            } else {
                // invalid cursor?
                return;
            }
            lastCursorResource = what;
        }
        if (useBuiltinCursor) {
            if ($swf10) { Mouse['cursor'] = what; }
            cursorSprite.stopDrag();
            cursorSprite.visible = false;
            LFCApplication.stage.removeEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
            LFCApplication.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
            Mouse.show();
        } else {
            // you can only hide the Mouse when Mouse.cursor is AUTO
            if ($swf10) { Mouse['cursor'] = MouseCursor.AUTO; }
            Mouse.hide();
            cursorSprite.x = LFCApplication.stage.mouseX + cursorOffsetX;
            cursorSprite.y = LFCApplication.stage.mouseY + cursorOffsetY;
            LFCApplication.setChildIndex(cursorSprite, LFCApplication._sprite.numChildren-1);
            // respond to mouse move events
            cursorSprite.startDrag();
            LFCApplication.stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
            cursorSprite.visible = true;
        }
    }

    /**
     * Triggered when cursor leaves screen or context-menu is opened, in both
     * cases we must display the system cursor
     */
    private static function mouseLeaveHandler (event:Event) :void {
        cursorSprite.visible = false;
        Mouse.show();
        // use capture-phase because most sprites call stopPropagation() for mouse-events
        LFCApplication.stage.addEventListener(MouseEvent.MOUSE_OVER, mouseEnterHandler, true);
    }

    /**
     * Triggered when cursor enters screen or context-menu is closed
     */
    private static function mouseEnterHandler (event:Event) :void {
        cursorSprite.visible = true;
        Mouse.hide();
        LFCApplication.stage.removeEventListener(MouseEvent.MOUSE_OVER, mouseEnterHandler, true);
    }

    /**
     * Hide custom cursor over selectable TextFields otherwise both the ibeam-cursor
     * and the custom cursor are displayed
     */
    private static function mouseMoveHandler (event:MouseEvent) :void {
        var target:Object = event.target;
        if (target is TextField && target.selectable) {
            cursorSprite.visible = false;
            Mouse.show();
        } else {
            Mouse.hide();
            cursorSprite.visible = true;
        }
    }

    private static function getCursorResource (resource:String) :DisplayObject {
        var resinfo:Object = LzResourceLibrary[resource];
        var assetclass:Class;
        if (resinfo == null) {
            return null;
        }
        // single frame resources get an entry in LzResourceLibrary which has
        // 'assetclass' pointing to the resource Class object.
        if (resinfo.assetclass is Class) {
            assetclass = resinfo.assetclass;
        } else {
            // Multiframe resources have an array of Class objects in frames[]
            var frames:Array = resinfo.frames;
            assetclass = frames[0];
        }

        var asset:DisplayObject = new assetclass();
        asset.scaleX = 1.0;
        asset.scaleY = 1.0;

        if (resinfo['offsetx'] != null) { cursorOffsetX = resinfo['offsetx']; }
        if (resinfo['offsety'] != null) { cursorOffsetY = resinfo['offsety']; }

        return asset;
    }

    /**
    * This function restores the default cursor if there is no locked cursor on
    * the screen.
    *
    * @access private
    */
    static function restoreCursor () :void {
        if ( __amLocked ) { return; }
        cursorSprite.stopDrag();
        cursorSprite.visible = false;
        LFCApplication.stage.removeEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
        LFCApplication.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
        globalCursorResource = null;
        if ($swf10) { Mouse['cursor'] = MouseCursor.AUTO; }
        Mouse.show();
    }

    /** Called by LzSprite to restore cursor to global value.
     */
    static function restoreCursorLocal () :void {
        if ( __amLocked ) { return; }
        if (globalCursorResource == null) {
            // Restore to system default pointer
            restoreCursor();
        } else {
            // Restore to the last value set by setCursorGlobal
            setCursorLocal(globalCursorResource);
        }
    }

    /**
    * Prevents the cursor from being changed until unlock is called.
    *
    */
    static function lock () :void {
        __amLocked = true;
    }

    /**
    * Restores the default cursor.
    *
    */
    static function unlock () :void {
        __amLocked = false;
        restoreCursor();
    }

    static function initCursor () :void {
        cursorSprite = new Sprite();
        cursorSprite.mouseChildren = false;
        cursorSprite.mouseEnabled = false;
        cursorSprite.visible = false;
        // Add the cursor DisplayObject to the root sprite
        LFCApplication.addChild(cursorSprite);
        cursorSprite.x = -10000;
        cursorSprite.y = -10000;
    }
}

/**
  * LzMouseKernel.as
  *
  * @copyright Copyright 2001-2010 Laszlo Systems, Inc.  All Rights Reserved.
  *            Use is subject to license terms.
  *
  * @topic Kernel
  * @subtopic swf9
  */

// Receives mouse events from the runtime
class LzMouseKernel  {
    #passthrough (toplevel:true) {
    import flash.display.Sprite;
    import flash.display.DisplayObject;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.ui.*;
    import flash.utils.getDefinitionByName;
    }#

    //////////////////
    // MOUSE EVENTS //
    //////////////////

    // sends mouse events to the callback
    static function handleMouseEvent (view:*, eventname:String) :void {
        if (__callback) __scope[__callback](eventname, view);
        //Debug.write('LzMouseKernel event', eventname);
    }

    static var __callback:String = null;
    static var __scope:* = null;
    static var __lastMouseDown:LzSprite = null;
    static var __mouseLeft:Boolean = false;
    static var __listeneradded:Boolean = false;

    /**
     * Shows or hides the hand cursor for all clickable views.
     */
    static var showhandcursor:Boolean = true;

    static function setCallback (scope:*, funcname:String) :void {
        __scope = scope;
        __callback = funcname;
        if (__listeneradded == false) {
            /* TODO [hqm 2008-01] Do we want to do anything with other
            * events, like click?
            stage.addEventListener(MouseEvent.CLICK, reportClick);
            */

            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_MOVE, __mouseHandler);
            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_UP,   __mouseHandler);
            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_DOWN, __mouseHandler);
            // handled by lz.embed.mousewheel for Windows LFCApplication.stage.addEventListener(MouseEvent.MOUSE_WHEEL, __mouseWheelHandler);
            LFCApplication.stage.addEventListener(Event.MOUSE_LEAVE, __mouseLeaveHandler);
            __listeneradded = true;
        }
    }

    // Handles global mouse events
    static function __mouseHandler (event:MouseEvent) :void {
        var eventname:String = 'on' + event.type.toLowerCase();
        if (eventname == 'onmouseup' && __lastMouseDown != null) {
            // call mouseup on the sprite that got the last mouse down
            __lastMouseDown.__globalmouseup(event);
            __lastMouseDown = null;
        } else {
            if (__mouseLeft) {
                __mouseLeft = false;
                // Mouse reentered the app.
                if (event.buttonDown) __mouseUpOutsideHandler();

                if (lz.embed.browser && lz.embed.browser.isFirefox && lz.embed.browser.OS == 'Mac' && lz.embed.browser.version < 3.5) {
                    // TODO [hqm 2009-04] LPP-7957 -- this works
                    // around Firefox bug; if you are making a text
                    // selection, and then drag the mouse outside of
                    // the app while the left button is down, and then
                    // release it. When you bring the mouse back into
                    // the app, the selection is stuck dragging
                    // because Flash plugin never gets the mouse up.
                    LFCApplication.stage.focus = null;
                }

                // generate a 'onmouseenter' event
                handleMouseEvent(null, 'onmouseenter');
            }
            handleMouseEvent(null, eventname);
        }
    }

    // sends mouseup and calls __globalmouseup when the mouse goes up outside the app - see LPP-7724
    static function __mouseUpOutsideHandler () :void {
        if (__lastMouseDown != null) {
            var ev:MouseEvent = new MouseEvent('mouseup');
            __lastMouseDown.__globalmouseup(ev);
            __lastMouseDown = null;
        }
    }

    // handles MOUSE_LEAVE event
    static function __mouseLeaveHandler (event:Event = null) :void {
        __mouseLeft = true;
        handleMouseEvent(null, 'onmouseleave');
    }

    static function __mouseWheelHandler (event:MouseEvent) :void {
        lz.Keys.__mousewheelEvent(event.delta);
    }

    //////////////////
    // MOUSE CURSOR //
    //////////////////

    /**
    * Shows or hides the hand cursor for all clickable views.
    * @param Boolean show: true shows the hand cursor for buttons, false hides it
    */
    static function showHandCursor (show:Boolean) :void {
        showhandcursor = show;
        LzSprite.rootSprite.setGlobalHandCursor(show);
    }

    static var __amLocked:Boolean = false;
    static var useBuiltinCursor:Boolean = false;
    static var cursorSprite:Sprite = null;
    static var cursorOffsetX:int = 0;
    static var cursorOffsetY:int = 0;
    static var globalCursorResource:String = null;
    static var lastCursorResource:String = null;

    #passthrough {
        private static var __MouseCursor:Object = null;
        private static function get MouseCursor () :Object {
            if (__MouseCursor == null) {
                __MouseCursor = getDefinitionByName('flash.ui.MouseCursor');
            }
            return __MouseCursor;
        }

        private static var __builtinCursors:Object = null;
        static function get builtinCursors () :Object {
            if (__builtinCursors == null) {
                var cursors:Object = {};
                if ($swf10) {
                    cursors[MouseCursor.ARROW] = true;
                    cursors[MouseCursor.AUTO] = true;
                    cursors[MouseCursor.BUTTON] = true;
                    cursors[MouseCursor.HAND] = true;
                    cursors[MouseCursor.IBEAM] = true;
                }
                __builtinCursors = cursors;
            }
            return __builtinCursors;
        }

        static function get hasGlobalCursor () :Boolean {
            var gcursor:String = globalCursorResource;
            if ($swf10) {
                return ! (gcursor == null || (gcursor == MouseCursor.AUTO && useBuiltinCursor));
            } else {
                return ! (gcursor == null);
            }
        }
    }#

    /**
    * Sets the cursor to a resource
    * @param String what: The resource to use as the cursor.
    */
    static function setCursorGlobal (what:String) :void {
        globalCursorResource = what;
        setCursorLocal(what);
    }

    static function setCursorLocal (what:String) :void {
        if ( __amLocked ) { return; }
        if (what == null) {
            // null is invalid, maybe call restoreCursor()?
            return;
        } else if (lastCursorResource != what) {
            var resourceSprite:DisplayObject = getCursorResource(what);
            if (resourceSprite != null) {
                if (cursorSprite.numChildren > 0) {
                    cursorSprite.removeChildAt(0);
                }
                cursorSprite.addChild( resourceSprite );
                useBuiltinCursor = false;
            } else if (builtinCursors[what] != null) {
                useBuiltinCursor = true;
            } else {
                // invalid cursor?
                return;
            }
            lastCursorResource = what;
        }
        if (useBuiltinCursor) {
            if ($swf10) { Mouse['cursor'] = what; }
            cursorSprite.stopDrag();
            cursorSprite.visible = false;
            LFCApplication.stage.removeEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
            LFCApplication.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
            Mouse.show();
        } else {
            // you can only hide the Mouse when Mouse.cursor is AUTO
            if ($swf10) { Mouse['cursor'] = MouseCursor.AUTO; }
            Mouse.hide();
            cursorSprite.x = LFCApplication.stage.mouseX + cursorOffsetX;
            cursorSprite.y = LFCApplication.stage.mouseY + cursorOffsetY;
            LFCApplication.setChildIndex(cursorSprite, LFCApplication._sprite.numChildren-1);
            // respond to mouse move events
            cursorSprite.startDrag();
            LFCApplication.stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
            LFCApplication.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
            cursorSprite.visible = true;
        }
    }

    /**
     * Triggered when cursor leaves screen or context-menu is opened, in both
     * cases we must display the system cursor
     */
    private static function mouseLeaveHandler (event:Event) :void {
        cursorSprite.visible = false;
        Mouse.show();
        // use capture-phase because most sprites call stopPropagation() for mouse-events
        LFCApplication.stage.addEventListener(MouseEvent.MOUSE_OVER, mouseEnterHandler, true);
    }

    /**
     * Triggered when cursor enters screen or context-menu is closed
     */
    private static function mouseEnterHandler (event:Event) :void {
        cursorSprite.visible = true;
        Mouse.hide();
        LFCApplication.stage.removeEventListener(MouseEvent.MOUSE_OVER, mouseEnterHandler, true);
    }

    /**
     * Hide custom cursor over selectable TextFields otherwise both the ibeam-cursor
     * and the custom cursor are displayed
     */
    private static function mouseMoveHandler (event:MouseEvent) :void {
        var target:Object = event.target;
        if (target is TextField && target.selectable) {
            cursorSprite.visible = false;
            Mouse.show();
        } else {
            Mouse.hide();
            cursorSprite.visible = true;
        }
    }

    private static function getCursorResource (resource:String) :DisplayObject {
        var resinfo:Object = LzResourceLibrary[resource];
        var assetclass:Class;
        if (resinfo == null) {
            return null;
        }
        // single frame resources get an entry in LzResourceLibrary which has
        // 'assetclass' pointing to the resource Class object.
        if (resinfo.assetclass is Class) {
            assetclass = resinfo.assetclass;
        } else {
            // Multiframe resources have an array of Class objects in frames[]
            var frames:Array = resinfo.frames;
            assetclass = frames[0];
        }

        var asset:DisplayObject = new assetclass();
        asset.scaleX = 1.0;
        asset.scaleY = 1.0;

        if (resinfo['offsetx'] != null) { cursorOffsetX = resinfo['offsetx']; }
        if (resinfo['offsety'] != null) { cursorOffsetY = resinfo['offsety']; }

        return asset;
    }

    /**
    * This function restores the default cursor if there is no locked cursor on
    * the screen.
    *
    * @access private
    */
    static function restoreCursor () :void {
        if ( __amLocked ) { return; }
        cursorSprite.stopDrag();
        cursorSprite.visible = false;
        LFCApplication.stage.removeEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
        LFCApplication.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
        globalCursorResource = null;
        if ($swf10) { Mouse['cursor'] = MouseCursor.AUTO; }
        Mouse.show();
    }

    /** Called by LzSprite to restore cursor to global value.
     */
    static function restoreCursorLocal () :void {
        if ( __amLocked ) { return; }
        if (globalCursorResource == null) {
            // Restore to system default pointer
            restoreCursor();
        } else {
            // Restore to the last value set by setCursorGlobal
            setCursorLocal(globalCursorResource);
        }
    }

    /**
    * Prevents the cursor from being changed until unlock is called.
    *
    */
    static function lock () :void {
        __amLocked = true;
    }

    /**
    * Restores the default cursor.
    *
    */
    static function unlock () :void {
        __amLocked = false;
        restoreCursor();
    }

    static function initCursor () :void {
        cursorSprite = new Sprite();
        cursorSprite.mouseChildren = false;
        cursorSprite.mouseEnabled = false;
        cursorSprite.visible = false;
        // Add the cursor DisplayObject to the root sprite
        LFCApplication.addChild(cursorSprite);
        cursorSprite.x = -10000;
        cursorSprite.y = -10000;
    }
}

Change 20100224-maxcarlson-n by maxcarlson@bank on 2010-02-24 11:14:21 PST
    in /Users/maxcarlson/openlaszlo/trunk-clean
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: UPDATED: Conditionalize textfield focus workaround from LPP-7957

Bugs Fixed: LPP-8783 - Text field loses focus when mousing out of canvas and then mousing back in (SWF9)

Technical Reviewer: ptw
QA Reviewer: andre.bargull@udo.edu

Details: Test for lz.embed.browser, and correct case in test for 'Mac'.  Conditionalize workaround to only happen for FF < 3.5 on OS X.

Tests: See LPP-8783.

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


package htmlelements
{
	import flash.display.Sprite;
	import flash.events.*;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.media.Video;
	import flash.media.SoundTransform;
	import flash.utils.Timer;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
    import flash.net.URLRequestMethod;
    import flash.display.MovieClip;
	 import flash.display.Loader;
	 import flash.display.DisplayObject;

	import FlashMediaElement;
	import HtmlMediaEvent;

	public class YouTubeElement extends Sprite implements IMediaElement
	{
		private var _currentUrl:String = "";
		private var _autoplay:Boolean = true;
		private var _preload:String = "";

		private var _element:FlashMediaElement;

		// event values
		private var _currentTime:Number = 0;
		private var _duration:Number = 0;
		private var _framerate:Number;
		private var _isPaused:Boolean = true;
		private var _isEnded:Boolean = false;
		private var _volume:Number = 1;
		private var _isMuted:Boolean = false;

		private var _bytesLoaded:Number = 0;
		private var _bytesTotal:Number = 0;
		private var _bufferedTime:Number = 0;
		private var _bufferEmpty:Boolean = false;

		private var _videoWidth:Number = -1;
		private var _videoHeight:Number = -1;

		private var _timer:Timer;

		// YouTube stuff
		private var _playerLoader:Loader;
		private var _player:Object = null;
		private var _playerIsLoaded:Boolean = false;
		private var _youTubeId:String = "";

		//http://code.google.com/p/gdata-samples/source/browse/trunk/ytplayer/actionscript3/com/google/youtube/examples/AS3Player.as
		private static const WIDESCREEN_ASPECT_RATIO:String = "widescreen";
		private static const QUALITY_TO_PLAYER_WIDTH:Object = {
			small: 320,
			medium: 640,
			large: 854,
			hd720: 1280
		};
		private static const STATE_ENDED:Number = 0;
		private static const STATE_PLAYING:Number = 1;
		private static const STATE_PAUSED:Number = 2;
		private static const STATE_CUED:Number = 5;

		public function get player():DisplayObject {
			return _player;
		}

		public function setSize(width:Number, height:Number):void {
			if (_player != null) {
				_player.setSize(width, height);
			}
		}

		public function get videoHeight():Number {
			return _videoHeight;
		}

		public function get videoWidth():Number {
			return _videoWidth;
		}

		public function duration():Number {
			return _duration;
		}

		public function currentProgress():Number {
			if(_bytesTotal> 0) {
				return Math.round(_bytesLoaded/_bytesTotal*100);
			} else {
				return 0;
			}
		}

		public function currentTime():Number {
			return _currentTime;
		}

		public var initHeight:Number;
		public var initWidth:Number;

		// (1) load()
		// calls _connection.connect();
		// waits for NetConnection.Connect.Success
		// _stream gets created

		public function YouTubeElement(element:FlashMediaElement, autoplay:Boolean, preload:String, timerRate:Number, startVolume:Number)
		{
			_element = element;
			_autoplay = autoplay;
			_volume = startVolume;
			_preload = preload;
			initHeight = 0;
			initWidth = 0;

			_playerLoader = new Loader();
			_playerLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, playerLoaderInitHandler);
			_playerLoader.load(new URLRequest("http://www.youtube.com/apiplayer?version=3"));

			_timer = new Timer(timerRate);
			_timer.addEventListener("timer", timerHandler);
			_timer.start();
		}

		private function playerLoaderInitHandler(event:Event):void {
			_element.addChild(_playerLoader.content);
			_element.setControlDepth();
			_playerLoader.content.addEventListener("onReady", onPlayerReady);
			_playerLoader.content.addEventListener("onError", onPlayerError);
			_playerLoader.content.addEventListener("onStateChange", onPlayerStateChange);
			_playerLoader.content.addEventListener("onPlaybackQualityChange", onVideoPlaybackQualityChange);
		}

		private function onPlayerReady(event:Event):void {
			_playerIsLoaded = true;

			_player = _playerLoader.content;

			if (initHeight > 0 && initWidth > 0)
				_player.setSize(initWidth, initHeight);

			if (_youTubeId != "") {
				if (_autoplay) {
					player.loadVideoById(_youTubeId);
				} else {
					player.cueVideoById(_youTubeId);
				}
				_timer.start();
			}
		}

		private function onPlayerError(event:Event):void {
			// trace("Player error:", Object(event).data);
		}

		private function onPlayerStateChange(event:Event):void {
			trace("State is", Object(event).data);

			_duration = _player.getDuration();

			switch (Object(event).data) {
				case STATE_ENDED:
					_isEnded = true;
					_isPaused = false;

					sendEvent(HtmlMediaEvent.ENDED);

					break;

				case STATE_PLAYING:
					_isEnded = false;
					_isPaused = false;

					sendEvent(HtmlMediaEvent.PLAY);
					sendEvent(HtmlMediaEvent.PLAYING);
					break;

				case STATE_PAUSED:
					_isEnded = false;
					_isPaused = true;

					sendEvent(HtmlMediaEvent.PAUSE);

					break;

				case STATE_CUED:
					sendEvent(HtmlMediaEvent.CANPLAY);

					// resize?

					break;
			}
		}

		private function onVideoPlaybackQualityChange(event:Event):void {
			trace("Current video quality:", Object(event).data);
			//resizePlayer(Object(event).data);
		}

		private function timerHandler(e:TimerEvent) {

			if (_playerIsLoaded) {
				_bytesLoaded = _player.getVideoBytesLoaded();
				_bytesTotal = _player.getVideoBytesTotal();
				_currentTime = player.getCurrentTime();

				if (!_isPaused)
					sendEvent(HtmlMediaEvent.TIMEUPDATE);

				if (_bytesLoaded < _bytesTotal)
					sendEvent(HtmlMediaEvent.PROGRESS);
			}

		}

		private function getYouTubeId(url:String):String {
			// http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0
			// http://www.youtube.com/v/VIDEO_ID?version=3
			// http://youtu.be/Djd6tPrxc08

			url = unescape(url);

			var youTubeId:String = "";

			if (url.indexOf("?") > 0) {
				// assuming: http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0
				youTubeId = getYouTubeIdFromParam(url);

				// if it's http://www.youtube.com/v/VIDEO_ID?version=3
				if (youTubeId == "") {
					youTubeId = getYouTubeIdFromUrl(url);
				}
			} else {
				youTubeId = getYouTubeIdFromUrl(url);
			}

			return youTubeId;
		}

		// http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0
		private function getYouTubeIdFromParam(url:String):String {

			var youTubeId:String = "";
			var parts:Array = url.split('?');
			var parameters:Array = parts[1].split('&');

			for (var i:Number=0; i<parameters.length; i++) {
				var paramParts = parameters[i].split('=');
				if (paramParts[0] == "v") {

					youTubeId = paramParts[1];
					break;
				}

			}

			return youTubeId;
		}

		// http://www.youtube.com/v/VIDEO_ID?version=3
		// http://youtu.be/Djd6tPrxc08
		private function getYouTubeIdFromUrl(url:String):String {

			var youTubeId:String = "";

			// remove any querystring elements
			var parts:Array = url.split('?');
			url = parts[0];

			youTubeId = url.substring(url.lastIndexOf("/")+1);

			return youTubeId;
		}

		// interface members
		public function setSrc(url:String):void {
			_currentUrl = url;

			_youTubeId = getYouTubeId(url);

		}

		public function load():void {
			// do nothing

			if (_playerIsLoaded) {
				player.loadVideoById(_youTubeId);
				_timer.start();
			}

		}

		public function play():void {
			if (_playerIsLoaded) {
				_player.playVideo();
			}

		}

		public function pause():void {
			if (_playerIsLoaded) {
				_player.pauseVideo();
			}
		}

		public function stop():void {
			if (_playerIsLoaded) {
				_player.pauseVideo();
			}
		}

		public function setCurrentTime(pos:Number):void {
			_player.seekTo(pos, false);
		}

		public function setVolume(volume:Number):void {
			_player.setVolume(volume*100);
			_volume = volume;
		}

		public function getVolume():Number {
			return _player.getVolume()*100;
		}

		public function setMuted(muted:Boolean):void {
			if (muted) {
				_player.mute();

			} else {
				_player.unMute();
			}
			_muted = _player.isMuted();
			sendEvent(HtmlMediaEvent.VOLUMECHANGE);
		}

		private function sendEvent(eventName:String) {

			// calculate this to mimic HTML5
			_bufferedTime = _bytesLoaded / _bytesTotal * _duration;

			// build JSON
			var values:String =
							"duration:" + _duration +
							",framerate:" + _framerate +
							",currentTime:" + _currentTime +
							",muted:" + _isMuted +
							",paused:" + _isPaused +
							",ended:" + _isEnded +
							",volume:" + _volume +
							",src:\"" + _currentUrl + "\"" +
							",bytesTotal:" + _bytesTotal +
							",bufferedBytes:" + _bytesLoaded +
							",bufferedTime:" + _bufferedTime +
							",videoWidth:" + _videoWidth +
							",videoHeight:" + _videoHeight +
							"";

			_element.sendEvent(eventName, values);
		}
	}
}

package htmlelements
{
	import flash.display.Sprite;
	import flash.events.*;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.media.Video;
	import flash.media.SoundTransform;
	import flash.utils.Timer;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
    import flash.net.URLRequestMethod;
    import flash.display.MovieClip;
	 import flash.display.Loader;
	 import flash.display.DisplayObject;

	import FlashMediaElement;
	import HtmlMediaEvent;

	public class YouTubeElement extends Sprite implements IMediaElement
	{
		private var _currentUrl:String = "";
		private var _autoplay:Boolean = true;
		private var _preload:String = "";

		private var _element:FlashMediaElement;

		// event values
		private var _currentTime:Number = 0;
		private var _duration:Number = 0;
		private var _framerate:Number;
		private var _isPaused:Boolean = true;
		private var _isEnded:Boolean = false;
		private var _volume:Number = 1;
		private var _isMuted:Boolean = false;

		private var _bytesLoaded:Number = 0;
		private var _bytesTotal:Number = 0;
		private var _bufferedTime:Number = 0;
		private var _bufferEmpty:Boolean = false;

		private var _videoWidth:Number = -1;
		private var _videoHeight:Number = -1;

		private var _timer:Timer;

		// YouTube stuff
		private var _playerLoader:Loader;
		private var _player:Object = null;
		private var _playerIsLoaded:Boolean = false;
		private var _youTubeId:String = "";

		//http://code.google.com/p/gdata-samples/source/browse/trunk/ytplayer/actionscript3/com/google/youtube/examples/AS3Player.as
		private static const WIDESCREEN_ASPECT_RATIO:String = "widescreen";
		private static const QUALITY_TO_PLAYER_WIDTH:Object = {
			small: 320,
			medium: 640,
			large: 854,
			hd720: 1280
		};
		private static const STATE_ENDED:Number = 0;
		private static const STATE_PLAYING:Number = 1;
		private static const STATE_PAUSED:Number = 2;
		private static const STATE_CUED:Number = 5;

		public function get player():DisplayObject {
			return _player;
		}

		public function setSize(width:Number, height:Number):void {
			if (_player != null) {
				_player.setSize(width, height);
			}
		}

		public function get videoHeight():Number {
			return _videoHeight;
		}

		public function get videoWidth():Number {
			return _videoWidth;
		}

		public function duration():Number {
			return _duration;
		}

		public function currentProgress():Number {
			if(_bytesTotal> 0) {
				return Math.round(_bytesLoaded/_bytesTotal*100);
			} else {
				return 0;
			}
		}

		public function currentTime():Number {
			return _currentTime;
		}

		public var initHeight:Number;
		public var initWidth:Number;

		// (1) load()
		// calls _connection.connect();
		// waits for NetConnection.Connect.Success
		// _stream gets created

		private var _isChromeless:Boolean = false;

		public function YouTubeElement(element:FlashMediaElement, autoplay:Boolean, preload:String, timerRate:Number, startVolume:Number)
		{
			_element = element;
			_autoplay = autoplay;
			_volume = startVolume;
			_preload = preload;
			initHeight = 0;
			initWidth = 0;

			_playerLoader = new Loader();
			_playerLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, playerLoaderInitHandler);

			// chromeless
			if (_isChromeless) {
				_playerLoader.load(new URLRequest("http://www.youtube.com/apiplayer?version=3&controls=1&rel=0&showinfo=0&iv_load_policy=1"));
			}

			_timer = new Timer(timerRate);
			_timer.addEventListener("timer", timerHandler);
			_timer.start();
		}

		private function playerLoaderInitHandler(event:Event):void {

			trace("yt player init");

			_element.addChild(_playerLoader.content);
			_element.setControlDepth();
			_playerLoader.content.addEventListener("onReady", onPlayerReady);
			_playerLoader.content.addEventListener("onError", onPlayerError);
			_playerLoader.content.addEventListener("onStateChange", onPlayerStateChange);
			_playerLoader.content.addEventListener("onPlaybackQualityChange", onVideoPlaybackQualityChange);
		}

		private function onPlayerReady(event:Event):void {
			_playerIsLoaded = true;

			_player = _playerLoader.content;

			if (initHeight > 0 && initWidth > 0)
				_player.setSize(initWidth, initHeight);

			if (_youTubeId != "") { //  && _isChromeless) {
				if (_autoplay) {
					player.loadVideoById(_youTubeId);
				} else {
					player.cueVideoById(_youTubeId);
				}
				_timer.start();
			}
		}

		private function onPlayerError(event:Event):void {
			// trace("Player error:", Object(event).data);
		}

		private function onPlayerStateChange(event:Event):void {
			trace("State is", Object(event).data);

			_duration = _player.getDuration();

			switch (Object(event).data) {
				case STATE_ENDED:
					_isEnded = true;
					_isPaused = false;

					sendEvent(HtmlMediaEvent.ENDED);

					break;

				case STATE_PLAYING:
					_isEnded = false;
					_isPaused = false;

					sendEvent(HtmlMediaEvent.PLAY);
					sendEvent(HtmlMediaEvent.PLAYING);
					break;

				case STATE_PAUSED:
					_isEnded = false;
					_isPaused = true;

					sendEvent(HtmlMediaEvent.PAUSE);

					break;

				case STATE_CUED:
					sendEvent(HtmlMediaEvent.CANPLAY);

					// resize?

					break;
			}
		}

		private function onVideoPlaybackQualityChange(event:Event):void {
			trace("Current video quality:", Object(event).data);
			//resizePlayer(Object(event).data);
		}

		private function timerHandler(e:TimerEvent) {

			if (_playerIsLoaded) {
				_bytesLoaded = _player.getVideoBytesLoaded();
				_bytesTotal = _player.getVideoBytesTotal();
				_currentTime = player.getCurrentTime();

				if (!_isPaused)
					sendEvent(HtmlMediaEvent.TIMEUPDATE);

				if (_bytesLoaded < _bytesTotal)
					sendEvent(HtmlMediaEvent.PROGRESS);
			}

		}

		private function getYouTubeId(url:String):String {
			// http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0
			// http://www.youtube.com/v/VIDEO_ID?version=3
			// http://youtu.be/Djd6tPrxc08

			url = unescape(url);

			var youTubeId:String = "";

			if (url.indexOf("?") > 0) {
				// assuming: http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0
				youTubeId = getYouTubeIdFromParam(url);

				// if it's http://www.youtube.com/v/VIDEO_ID?version=3
				if (youTubeId == "") {
					youTubeId = getYouTubeIdFromUrl(url);
				}
			} else {
				youTubeId = getYouTubeIdFromUrl(url);
			}

			return youTubeId;
		}

		// http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0
		private function getYouTubeIdFromParam(url:String):String {

			var youTubeId:String = "";
			var parts:Array = url.split('?');
			var parameters:Array = parts[1].split('&');

			for (var i:Number=0; i<parameters.length; i++) {
				var paramParts = parameters[i].split('=');
				if (paramParts[0] == "v") {

					youTubeId = paramParts[1];
					break;
				}

			}

			return youTubeId;
		}

		// http://www.youtube.com/v/VIDEO_ID?version=3
		// http://youtu.be/Djd6tPrxc08
		private function getYouTubeIdFromUrl(url:String):String {

			var youTubeId:String = "";

			// remove any querystring elements
			var parts:Array = url.split('?');
			url = parts[0];

			youTubeId = url.substring(url.lastIndexOf("/")+1);

			return youTubeId;
		}

		// interface members
		public function setSrc(url:String):void {
			trace("yt setSrc()" + url );

			_currentUrl = url;

			_youTubeId = getYouTubeId(url);

			if (!_playerIsLoaded && !_isChromeless) {
				_playerLoader.load(new URLRequest("http://www.youtube.com/v/" + _youTubeId + "?version=3&controls=0&rel=0&showinfo=0&iv_load_policy=1"));
			}
		}

		public function load():void {
			// do nothing
			trace("yt load()");

			if (_playerIsLoaded) {
				player.loadVideoById(_youTubeId);
				_timer.start();
			}  else {
				/*
				if (!_isChromless && _youTubeId != "") {
					_playerLoader.load(new URLRequest("http://www.youtube.com/v/" + _youTubeId + "?version=3&controls=0&rel=0&showinfo=0&iv_load_policy=1"));
				}
				*/
			}
		}

		public function play():void {
			if (_playerIsLoaded) {
				_player.playVideo();
			}

		}

		public function pause():void {
			if (_playerIsLoaded) {
				_player.pauseVideo();
			}
		}

		public function stop():void {
			if (_playerIsLoaded) {
				_player.pauseVideo();
			}
		}

		public function setCurrentTime(pos:Number):void {
			_player.seekTo(pos, false);
		}

		public function setVolume(volume:Number):void {
			_player.setVolume(volume*100);
			_volume = volume;
		}

		public function getVolume():Number {
			return _player.getVolume()*100;
		}

		public function setMuted(muted:Boolean):void {
			if (muted) {
				_player.mute();

			} else {
				_player.unMute();
			}
			_muted = _player.isMuted();
			sendEvent(HtmlMediaEvent.VOLUMECHANGE);
		}

		private function sendEvent(eventName:String) {

			// calculate this to mimic HTML5
			_bufferedTime = _bytesLoaded / _bytesTotal * _duration;

			// build JSON
			var values:String =
							"duration:" + _duration +
							",framerate:" + _framerate +
							",currentTime:" + _currentTime +
							",muted:" + _isMuted +
							",paused:" + _isPaused +
							",ended:" + _isEnded +
							",volume:" + _volume +
							",src:\"" + _currentUrl + "\"" +
							",bytesTotal:" + _bytesTotal +
							",bufferedBytes:" + _bytesLoaded +
							",bufferedTime:" + _bufferedTime +
							",videoWidth:" + _videoWidth +
							",videoHeight:" + _videoHeight +
							"";

			_element.sendEvent(eventName, values);
		}
	}
}

Update from Chromeless to normal player to support anntations


//
// Flump - Copyright 2012 Three Rings Design

package flump.xfl {

import flash.geom.Matrix;
import flash.geom.Point;

public class XflKeyframe extends XflComponent
{
    use namespace xflns;

    public var index :int;

    /** The length of this keyframe in frames. */
    public var duration :Number;

    /** The name of the libraryItem in this keyframe, or null if there is no libraryItem. */
    public var libraryItem :String;

    /** The name of the symbol in this keyframe, or null if there is no symbol. */
    public var symbol :String;

    /** The transform of the symbol in this keyframe, or null if libraryName is null. */
    public var matrix :Matrix;

    /** The label on this keyframe, or null if there isn't one */
    public var label :String;

    /** Exploded values from matrix */
    public var x :Number = 0.0, y :Number = 0.0, scaleX :Number = 1.0, scaleY :Number = 1.0,
        rotation :Number = 0.0;

    public function XflKeyframe (baseLocation :String, xml :XML, errors :Vector.<ParseError>,
        flipbook :Boolean) {
        const converter :XmlConverter = new XmlConverter(xml);
        index = converter.getIntAttr("index");
        super(baseLocation + ":" + index, errors);
        duration = converter.getNumberAttr("duration", 1);
        label = converter.getStringAttr("name", null);

        if (flipbook) return;
        var symbolXml :XML;
        for each (var frameEl :XML in xml.elements.elements()) {
            if (frameEl.name().localName == "DOMSymbolInstance") {
                if (symbolXml != null)  {
                    addError(ParseError.CRIT, "There can be only one symbol instance at " +
                        "a time in a keyframe.");
                } else symbolXml = frameEl;
            } else {
                addError(ParseError.CRIT, "Non-symbols may not be in exported movie " +
                    "layers");
            }
        }

        if (symbolXml == null) return; // Purely labelled frame

        if (!isClassicTween(xml)) {
            addError(ParseError.WARN, "Motion and Shape tweens are not supported");
        }

        libraryItem = new XmlConverter(symbolXml).getStringAttr("libraryItemName");

        const matrixXml :XML = symbolXml.matrix.Matrix[0];
        const matrixConverter :XmlConverter =
            matrixXml == null ? null : new XmlConverter(matrixXml);
        function m (name :String, def :Number) :Number {
            return matrixConverter == null ? def : matrixConverter.getNumberAttr(name, def);
        }
        matrix = new Matrix(m("a", 1), m("b", 0), m("c", 0), m("d", 1), m("tx", 0), m("ty", 0));

        x = matrix.tx;
        y = matrix.ty;
        var py :Point = matrix.deltaTransformPoint(new Point(1, 0));
        rotation = Math.atan2(py.y, py.x);
        scaleX = Math.sqrt((matrix.a * matrix.a) + (matrix.b * matrix.b));
        scaleY = Math.sqrt((matrix.c * matrix.c) + (matrix.d * matrix.d));
    }

    public function checkSymbols (lib :XflLibrary) :void {
        if (symbol != null && !lib.hasSymbol(symbol)) {
            addError(ParseError.CRIT, "Symbol '" + symbol + "' not exported");
        }
    }

    public function toJSON (_:*) :Object {
        var json :Object = {
            index: index,
            duration: duration
        };
        if (libraryItem != null) {
            json.ref = symbol;
            json.t = [ x, y, scaleX, scaleY, rotation ];
            // json.alpha = 1;
        }
        if (label != null) {
            json.label = label;
        }
        return json;
    }

    protected static function isClassicTween (xml :XML) :Boolean {
        const converter :XmlConverter = new XmlConverter(xml);
        if (converter.hasAttr("motionTweenRotate") ||
            converter.hasAttr("motionTweenRotateTimes")) {
            return false;
        }

        return true;
    }
}
}

//
// Flump - Copyright 2012 Three Rings Design

package flump.xfl {

import flash.geom.Matrix;
import flash.geom.Point;
import com.threerings.util.MatrixUtil;

public class XflKeyframe extends XflComponent
{
    use namespace xflns;

    public var index :int;

    /** The length of this keyframe in frames. */
    public var duration :Number;

    /** The name of the libraryItem in this keyframe, or null if there is no libraryItem. */
    public var libraryItem :String;

    /** The name of the symbol in this keyframe, or null if there is no symbol. */
    public var symbol :String;

    /** The transform of the symbol in this keyframe, or null if libraryName is null. */
    public var matrix :Matrix;

    /** The label on this keyframe, or null if there isn't one */
    public var label :String;

    /** Exploded values from matrix */
    public var x :Number = 0.0, y :Number = 0.0, scaleX :Number = 1.0, scaleY :Number = 1.0,
        rotation :Number = 0.0;

    public function XflKeyframe (baseLocation :String, xml :XML, errors :Vector.<ParseError>,
        flipbook :Boolean) {
        const converter :XmlConverter = new XmlConverter(xml);
        index = converter.getIntAttr("index");
        super(baseLocation + ":" + index, errors);
        duration = converter.getNumberAttr("duration", 1);
        label = converter.getStringAttr("name", null);

        if (flipbook) return;
        var symbolXml :XML;
        for each (var frameEl :XML in xml.elements.elements()) {
            if (frameEl.name().localName == "DOMSymbolInstance") {
                if (symbolXml != null)  {
                    addError(ParseError.CRIT, "There can be only one symbol instance at " +
                        "a time in a keyframe.");
                } else symbolXml = frameEl;
            } else {
                addError(ParseError.CRIT, "Non-symbols may not be in exported movie " +
                    "layers");
            }
        }

        if (symbolXml == null) return; // Purely labelled frame

        if (!isClassicTween(xml)) {
            addError(ParseError.WARN, "Motion and Shape tweens are not supported");
        }

        libraryItem = new XmlConverter(symbolXml).getStringAttr("libraryItemName");

        const matrixXml :XML = symbolXml.matrix.Matrix[0];
        const matrixConverter :XmlConverter =
            matrixXml == null ? null : new XmlConverter(matrixXml);
        function m (name :String, def :Number) :Number {
            return matrixConverter == null ? def : matrixConverter.getNumberAttr(name, def);
        }
        matrix = new Matrix(m("a", 1), m("b", 0), m("c", 0), m("d", 1), m("tx", 0), m("ty", 0));

        x = matrix.tx;
        y = matrix.ty;
        rotation = MatrixUtil.rotation(matrix);
        scaleX = MatrixUtil.scaleX(matrix);
        scaleY = MatrixUtil.scaleY(matrix);
    }

    public function checkSymbols (lib :XflLibrary) :void {
        if (symbol != null && !lib.hasSymbol(symbol)) {
            addError(ParseError.CRIT, "Symbol '" + symbol + "' not exported");
        }
    }

    public function toJSON (_:*) :Object {
        var json :Object = {
            index: index,
            duration: duration
        };
        if (libraryItem != null) {
            json.ref = symbol;
            json.t = [ x, y, scaleX, scaleY, rotation ];
            // json.alpha = 1;
        }
        if (label != null) {
            json.label = label;
        }
        return json;
    }

    protected static function isClassicTween (xml :XML) :Boolean {
        const converter :XmlConverter = new XmlConverter(xml);
        if (converter.hasAttr("motionTweenRotate") ||
            converter.hasAttr("motionTweenRotateTimes")) {
            return false;
        }

        return true;
    }
}
}

Use MatrixUtil

Use MatrixUtil


package aerys.minko.scene.controller
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.type.Signal;

	import flash.utils.getQualifiedClassName;

	/**
	 * Controllers work on scene nodes to modify and update them. They offer the best
	 * way to add any kind of behavior on one or multiple scene nodes. They can be used
	 * to create animations, add physics, artificial intelligence...
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class AbstractController
	{
		private var _targetType		: Class					= null;
		private var _targets		: Vector.<ISceneNode>	= new <ISceneNode>[];

		private var _targetAdded	: Signal				= new Signal('AbstractController.targetAdded');
		private var _targetRemoved	: Signal				= new Signal('AbstractController.targetRemoved');

		/**
		 * The number of scene nodes targeted by this very controller.
		 * @return
		 *
		 */
		public function get numTargets() : uint
		{
			return _targets.length;
		}

		/**
		 * The signal executed when a target is added to the controller.
		 * @return
		 *
		 */
		public function get targetAdded() : Signal
		{
			return _targetAdded;
		}

		/**
		 * The signal executed when a target is removed from the controller.
		 * @return
		 *
		 */
		public function get targetRemoved() : Signal
		{
			return _targetRemoved;
		}

		public function AbstractController(targetType : Class = null)
		{
			_targetType = targetType || ISceneNode;
		}

		/**
		 * Add a target to the controller.
		 * @param target
		 *
		 */
		minko_scene function addTarget(target : ISceneNode) : void
		{
			if (_targetType && !(target is _targetType))
			{
				throw new Error(
					'Controller \'' + getQualifiedClassName(this)
					+ ' cannot target objects from class \''
					+ getQualifiedClassName(target) + '\'.'
				);
			}

			_targets.push(target);

			_targetAdded.execute(this, target);
		}

		/**
		 * Remove a target from the controller.
		 * @param target
		 *
		 */
		minko_scene function removeTarget(target : ISceneNode) : void
		{
			var index : int = _targets.indexOf(target);
			var numTargets : int = _targets.length - 1;

			if (index < 0)
				throw new Error();

			_targets[index] = _targets[numTargets];
			_targets.length = numTargets;

			_targetRemoved.execute(this, target);
		}

		/**
		 * Get the target at the specified index.
		 * @param index
		 * @return
		 *
		 */
		public function getTarget(index : uint) : ISceneNode
		{
			return _targets[index];
		}

		public function clone() : AbstractController
		{
			throw new Error('The method AbstractController.clone() must be overriden.');
		}
	}
}

package aerys.minko.scene.controller
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.type.Signal;

	import flash.utils.getQualifiedClassName;

    use namespace minko_scene;

	/**
	 * Controllers work on scene nodes to modify and update them. They offer the best
	 * way to add any kind of behavior on one or multiple scene nodes. They can be used
	 * to create animations, add physics, artificial intelligence...
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class AbstractController
	{
		private var _targetType		: Class					= null;
		private var _targets		: Vector.<ISceneNode>	= new <ISceneNode>[];

		private var _targetAdded	: Signal				= new Signal('AbstractController.targetAdded');
		private var _targetRemoved	: Signal				= new Signal('AbstractController.targetRemoved');

		/**
		 * The number of scene nodes targeted by this very controller.
		 * @return
		 *
		 */
		public function get numTargets() : uint
		{
			return _targets.length;
		}

		/**
		 * The signal executed when a target is added to the controller.
		 * @return
		 *
		 */
		public function get targetAdded() : Signal
		{
			return _targetAdded;
		}

		/**
		 * The signal executed when a target is removed from the controller.
		 * @return
		 *
		 */
		public function get targetRemoved() : Signal
		{
			return _targetRemoved;
		}

		public function AbstractController(targetType : Class = null)
		{
			_targetType = targetType || ISceneNode;
		}

		/**
		 * Add a target to the controller.
		 * @param target
		 *
		 */
		minko_scene function addTarget(target : ISceneNode) : void
		{
			if (_targetType && !(target is _targetType))
			{
				throw new Error(
					'Controller \'' + getQualifiedClassName(this)
					+ ' cannot target objects from class \''
					+ getQualifiedClassName(target) + '\'.'
				);
			}

			_targets.push(target);

			_targetAdded.execute(this, target);
		}

		/**
		 * Remove a target from the controller.
		 * @param target
		 *
		 */
		minko_scene function removeTarget(target : ISceneNode) : void
		{
			var index : int = _targets.indexOf(target);
			var numTargets : int = _targets.length - 1;

			if (index < 0)
				throw new Error();

			_targets[index] = _targets[numTargets];
			_targets.length = numTargets;

			_targetRemoved.execute(this, target);
		}

		/**
		 * Get the target at the specified index.
		 * @param index
		 * @return
		 *
		 */
		public function getTarget(index : uint) : ISceneNode
		{
			return _targets[index];
		}

		public function clone() : AbstractController
		{
			throw new Error('The method AbstractController.clone() must be overriden.');
		}
	}
}

add missing use namespace minko_scene to allow the override of AbstractController.minko_scene::addTarget() and AbstractController.minko_scene::removeTarget()


/**
  * LFCApplication.as
  *
  * @copyright Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.
  *            Use is subject to license terms.
  *
  * @topic Kernel
  * @subtopic swf9
  * @author Henry Minsky <hminsky@laszlosystems.com>
  */

public class LFCApplication extends Sprite {

    // This serves as the superclass of DefaultApplication, currently that is where
    // the compiler puts top level code to run.

    #passthrough (toplevel:true) {
    import flash.display.*;
    import flash.events.*;
    import flash.utils.*;
    import flash.text.*;
    import flash.system.*;
    import flash.net.*;
    import flash.ui.*;
    import flash.text.Font;
    }#

    public function LFCApplication () {

        // Start up idle service timer. LzIdle is a global
        LzIdle = new LzIdleClass ();

        LzIdleKernel.addCallback( this, '__idleupdate' );

        var idleTimerPeriod = 14; // msecs
        //var idleTimerPeriod = 31; // msecs

        trace('idle timer period = ', idleTimerPeriod , 'msecs');
        LzIdleKernel.startTimer( idleTimerPeriod );

        stage.addEventListener(KeyboardEvent.KEY_DOWN,reportKeyDown);
        stage.addEventListener(KeyboardEvent.KEY_UP,reportKeyUp);

        // necessary for consistent behavior - in netscape browsers HTML is ignored
        stage.align = StageAlign.TOP_LEFT;
        stage.scaleMode = StageScaleMode.NO_SCALE;
        //Stage.align = ('canvassalign' in global && global.canvassalign != null) ? global.canvassalign : "LT";
        //Stage.scaleMode = ('canvasscale' in global && global.canvasscale != null) ? global.canvasscale : "noScale";

        stage.addEventListener(Event.RESIZE, resizeHandler);

        /* TODO [hqm 2008-01] Do we want to do anything with other
         * events, like click, or mousewheel ?

           stage.addEventListener(MouseEvent.CLICK, reportClick);
           stage.addEventListener(MouseEvent.MOUSE_WHEEL, reportWheel);
        */

        LzKeyboardKernel.setCallback(LzKeys, '__keyEvent');

        ////////////////////////////////////////////////////////////////
        // cheapo debug console
        lzconsole = this;
        var tfield:TextField = new TextField();
        tfield.background = true;
        tfield.backgroundColor = 0xcccccc;
        tfield.x = 0;
        tfield.y = 400;
        tfield.wordWrap = true;
        tfield.multiline = true;
        tfield.width = 800;
        tfield.height = 160;
        tfield.border = true;
        consoletext = tfield;

        var ci:TextField =  new TextField();
        consoleinputtext = ci;
        ci.background = true;
        ci.backgroundColor = 0xffcccc;
        ci.x = 0;
        ci.y = 560;
        ci.wordWrap = false;
        ci.multiline = false;
        ci.width = 800;
        ci.height = 20;
        ci.border = true;
        ci.type = TextFieldType.INPUT;
        ci.addEventListener(KeyboardEvent.KEY_DOWN, consoleInputHandler);

        /*        var allFonts:Array = Font.enumerateFonts(true);
        allFonts.sortOn("fontName", Array.CASEINSENSITIVE);

        var embeddedFonts:Array = Font.enumerateFonts(false);
        embeddedFonts.sortOn("fontName", Array.CASEINSENSITIVE);

        */

        var newFormat:TextFormat = new TextFormat();
        newFormat.size = 11;
        newFormat.font = "Verdana";
        ci.defaultTextFormat = newFormat;
        consoletext.defaultTextFormat = newFormat;

        ////////////////////////////////////////////////////////////////

        ////////////////////////////////////////////////////////////////
        // Testing runtime code loading
        ////////////////////////////////////////////////////////////////

    }

    var debugloader:Loader;

    // Debugger loader completion handler
    function debugEvalListener (e:Event):void {
        debugloader.unload();
        //DebugExec(e.target.content).doit();
    }

    function consoleInputHandler (event:KeyboardEvent ){
        if (event.charCode == Keyboard.ENTER) {
            var expr = consoleinputtext.text;
            write(expr);
            consoleinputtext.text = "";

            debugloader = new Loader();
            debugloader.contentLoaderInfo.addEventListener(Event.INIT, debugEvalListener);

            // Send EVAL request to LPS server
            // It doesn't matter what path/filename we use, as long as it has ".lzx" suffix, so it is
            // handled by the LPS. The lzt=eval causes the request to be served by the EVAL Responder.
            var url = "hello.lzx?lzr=swf9&lz_load=false&lzt=eval&lz_script=" + encodeURIComponent(expr)+"&lzbc=" +(new Date()).getTime();
            debugloader.load(new URLRequest(url),
                             new LoaderContext(false,
                                               new ApplicationDomain(ApplicationDomain.currentDomain)));
        }
    }

    ////////////////////////////////////////////////////////////////
    // A crude debugger output window for now
    public var consoletext:TextField;
    public var consoleinputtext:TextField;

    public function write (...args) {
        consoletext.appendText( "\n" + args.join(" "));
        consoletext.scrollV = consoletext.maxScrollV;
    }
    ////////////////////////////////////////////////////////////////

      function reportWheel(event:MouseEvent):void
    {
        trace(event.currentTarget.toString() +
              " dispatches MouseWheelEvent. delta = " + event.delta);
        //        LzKeys.__mousewheelEvent(event.delta);
    }

    function reportClick(event:MouseEvent):void
    {
        /*
          trace(event.currentTarget.toString() +
              " dispatches MouseEvent. Local coords [" +
              event.localX + "," + event.localY + "] Stage coords [" +
              event.stageX + "," + event.stageY + "]");
        */
    }

    function resizeHandler(event:Event):void {
        // event.target is a  pointer to the stage
        LzScreenKernel.handleResizeEvent(event.target);
    }

    function reportKeyUp(event:KeyboardEvent):void {
        /*
          trace("Key Released: " + String.fromCharCode(event.charCode) +
              " (key code: " + event.keyCode + " character code: " +
              event.charCode + ")");
        */
        LzKeyboardKernel.__keyboardEvent(event.charCode, 'onkeyup');
    }

    function reportKeyDown(event:KeyboardEvent):void {
        /*
          trace("Key Pressed: " + String.fromCharCode(event.charCode) +
              " (key code: " + event.keyCode + " character code: "
              + event.charCode + ")");
        */
        LzKeyboardKernel.__keyboardEvent(event.charCode, 'onkeydown');
    }

        /**
         * __idleupdate is a callback function from LzIdleKernel.
         * Treat it as a static function (ie. Don't reference 'this')
         * @access private
         */
    public function __idleupdate (etime) {
        var oi = LzIdle.onidle;
        if (oi.ready) {
            oi.sendEvent( etime );
        }
    }

}

// Resource library
// contains {ptype, class, frames, width, height}
// ptype is one of "ar" (app relative) or "sr" (system relative)
var LzResourceLibrary = {};
var lzconsole;

/**
  * LFCApplication.as
  *
  * @copyright Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.
  *            Use is subject to license terms.
  *
  * @topic Kernel
  * @subtopic swf9
  * @author Henry Minsky <hminsky@laszlosystems.com>
  */

public class LFCApplication extends Sprite {

    // This serves as the superclass of DefaultApplication, currently that is where
    // the compiler puts top level code to run.

    #passthrough (toplevel:true) {
    import flash.display.*;
    import flash.events.*;
    import flash.utils.*;
    import flash.text.*;
    import flash.system.*;
    import flash.net.*;
    import flash.ui.*;
    import flash.text.Font;
    }#

    public function LFCApplication () {

        // Start up idle service timer. LzIdle is a global
        LzIdle = new LzIdleClass ();

        LzIdleKernel.addCallback( this, '__idleupdate' );

        var idleTimerPeriod = 14; // msecs
        //var idleTimerPeriod = 31; // msecs

        trace('idle timer period = ', idleTimerPeriod , 'msecs');
        LzIdleKernel.startTimer( idleTimerPeriod );

        stage.addEventListener(KeyboardEvent.KEY_DOWN,reportKeyDown);
        stage.addEventListener(KeyboardEvent.KEY_UP,reportKeyUp);

        // necessary for consistent behavior - in netscape browsers HTML is ignored
        stage.align = StageAlign.TOP_LEFT;
        stage.scaleMode = StageScaleMode.NO_SCALE;
        //Stage.align = ('canvassalign' in global && global.canvassalign != null) ? global.canvassalign : "LT";
        //Stage.scaleMode = ('canvasscale' in global && global.canvasscale != null) ? global.canvasscale : "noScale";

        stage.addEventListener(Event.RESIZE, resizeHandler);

        /* TODO [hqm 2008-01] Do we want to do anything with other
         * events, like click, or mousewheel ?

           stage.addEventListener(MouseEvent.CLICK, reportClick);
           stage.addEventListener(MouseEvent.MOUSE_WHEEL, reportWheel);
        */

        LzKeyboardKernel.setCallback(LzKeys, '__keyEvent');

        ////////////////////////////////////////////////////////////////
        // cheapo debug console
        lzconsole = this;
        var tfield:TextField = new TextField();
        tfield.background = true;
        tfield.backgroundColor = 0xcccccc;
        tfield.x = 0;
        tfield.y = 400;
        tfield.wordWrap = true;
        tfield.multiline = true;
        tfield.width = 800;
        tfield.height = 160;
        tfield.border = true;
        consoletext = tfield;

        var ci:TextField =  new TextField();
        consoleinputtext = ci;
        ci.background = true;
        ci.backgroundColor = 0xffcccc;
        ci.x = 0;
        ci.y = 560;
        ci.wordWrap = false;
        ci.multiline = false;
        ci.width = 800;
        ci.height = 20;
        ci.border = true;
        ci.type = TextFieldType.INPUT;
        ci.addEventListener(KeyboardEvent.KEY_DOWN, consoleInputHandler);

        /*        var allFonts:Array = Font.enumerateFonts(true);
        allFonts.sortOn("fontName", Array.CASEINSENSITIVE);

        var embeddedFonts:Array = Font.enumerateFonts(false);
        embeddedFonts.sortOn("fontName", Array.CASEINSENSITIVE);

        */

        var newFormat:TextFormat = new TextFormat();
        newFormat.size = 11;
        newFormat.font = "Verdana";
        ci.defaultTextFormat = newFormat;
        consoletext.defaultTextFormat = newFormat;

        ////////////////////////////////////////////////////////////////

        ////////////////////////////////////////////////////////////////
        // Testing runtime code loading
        ////////////////////////////////////////////////////////////////

    }

    var debugloader:Loader;

    // Debugger loader completion handler
    function debugEvalListener (e:Event):void {
        debugloader.unload();
        //DebugExec(e.target.content).doit();
    }

    function consoleInputHandler (event:KeyboardEvent ){
        if (event.charCode == Keyboard.ENTER) {
            var expr = consoleinputtext.text;
            write(expr);
            consoleinputtext.text = "";

            debugloader = new Loader();
            debugloader.contentLoaderInfo.addEventListener(Event.INIT, debugEvalListener);

            // Send EVAL request to LPS server
            // It doesn't matter what path/filename we use, as long as it has ".lzx" suffix, so it is
            // handled by the LPS. The lzt=eval causes the request to be served by the EVAL Responder.
            var url = "hello.lzx?lzr=swf9&lz_load=false&lzt=eval&lz_script=" + encodeURIComponent(expr)+"&lzbc=" +(new Date()).getTime();
            debugloader.load(new URLRequest(url),
                             new LoaderContext(false,
                                               new ApplicationDomain(ApplicationDomain.currentDomain)));
        }
    }

    ////////////////////////////////////////////////////////////////
    // A crude debugger output window for now
    public var consoletext:TextField;
    public var consoleinputtext:TextField;

    public function write (...args) {
        consoletext.appendText( "\n" + args.join(" "));
        consoletext.scrollV = consoletext.maxScrollV;
    }
    ////////////////////////////////////////////////////////////////

      function reportWheel(event:MouseEvent):void
    {
        trace(event.currentTarget.toString() +
              " dispatches MouseWheelEvent. delta = " + event.delta);
        //        LzKeys.__mousewheelEvent(event.delta);
    }

    function reportClick(event:MouseEvent):void
    {
        /*
          trace(event.currentTarget.toString() +
              " dispatches MouseEvent. Local coords [" +
              event.localX + "," + event.localY + "] Stage coords [" +
              event.stageX + "," + event.stageY + "]");
        */
    }

    function resizeHandler(event:Event):void {
        // event.target is a  pointer to the stage
        //LzScreenKernel.handleResizeEvent(event.target);
    }

    function reportKeyUp(event:KeyboardEvent):void {
        /*
          trace("Key Released: " + String.fromCharCode(event.charCode) +
              " (key code: " + event.keyCode + " character code: " +
              event.charCode + ")");
        */
        LzKeyboardKernel.__keyboardEvent(event.charCode, 'onkeyup');
    }

    function reportKeyDown(event:KeyboardEvent):void {
        /*
          trace("Key Pressed: " + String.fromCharCode(event.charCode) +
              " (key code: " + event.keyCode + " character code: "
              + event.charCode + ")");
        */
        LzKeyboardKernel.__keyboardEvent(event.charCode, 'onkeydown');
    }

        /**
         * __idleupdate is a callback function from LzIdleKernel.
         * Treat it as a static function (ie. Don't reference 'this')
         * @access private
         */
    public function __idleupdate (etime) {
        var oi = LzIdle.onidle;
        if (oi.ready) {
            oi.sendEvent( etime );
        }
    }

}

// Resource library
// contains {ptype, class, frames, width, height}
// ptype is one of "ar" (app relative) or "sr" (system relative)
var LzResourceLibrary = {};
var lzconsole;

revert until LzScreenKernel gets checked in

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


package aerys.minko.render.shader.compiler.visitor.allocator
{
	import aerys.minko.render.shader.compiler.allocator.Allocator;
	import aerys.minko.render.shader.node.INode;
	import aerys.minko.render.shader.node.leaf.AbstractConstant;
	import aerys.minko.render.shader.node.leaf.Attribute;
	import aerys.minko.render.shader.node.operation.AbstractOperation;
	import aerys.minko.render.shader.node.operation.manipulation.Combine;
	import aerys.minko.render.shader.node.operation.manipulation.Interpolate;
	import aerys.minko.render.shader.node.operation.manipulation.Extract;

	public class VertexAllocator extends AbstractAllocator
	{
		protected var _attrAlloc	: Allocator;

		protected var _visited		: Vector.<INode>;
		protected var _stack		: Vector.<INode>;

		public function VertexAllocator(attrAlloc	: Allocator,
										tmpAlloc	: Allocator,
										constAlloc	: Allocator)
		{
			_operationId = 0;

			_attrAlloc		= attrAlloc;
			_tmpAlloc		= tmpAlloc;
			_constAlloc		= constAlloc;

			_visited		= new Vector.<INode>();
			_stack			= new Vector.<INode>();
		}

		public function processVertexShader(nodes:Vector.<INode>):void
		{
			for each (var node:INode in nodes)
				visit(node);
		}

		override public function visit(shaderNode : INode):void
		{
			if (_visited.indexOf(shaderNode) !== -1)
				return;

			_visited.push(shaderNode);
			_stack.push(shaderNode);

			shaderNode.accept(this);

			++_operationId;

			if (shaderNode is Interpolate || shaderNode is Extract)
			{
				reportOperationArgumentsUsage(AbstractOperation(shaderNode));
			}
			else if (shaderNode is Combine)
			{
				var combineNode : Combine = shaderNode as Combine;

				reportArgumentUsage(combineNode.arg1, false);
				_tmpAlloc.allocate(combineNode, _operationId);

				++_operationId;

				reportArgumentUsage(combineNode.arg2, false);
			}
			else if (shaderNode is AbstractOperation)
			{
				var operationNode : AbstractOperation = AbstractOperation(shaderNode);
				reportOperationArgumentsUsage(operationNode);

				// on ne traite pas le noeud final.
				if (_stack.length > 1)
					_tmpAlloc.allocate(operationNode, _operationId);
			}

			else if (shaderNode is Attribute)
				_attrAlloc.allocate(shaderNode);

			else if (shaderNode is AbstractConstant)
				_constAlloc.allocate(shaderNode);

			_stack.pop();
		}

		override protected function reportArgumentUsage(arg:INode, aligned : Boolean) : void
		{
			if (arg is Attribute)
				_attrAlloc.reportUsage(arg, _operationId, aligned);

			else if (arg is AbstractConstant)
				_constAlloc.reportUsage(arg, _operationId, aligned);

			else if (arg is Extract)
				reportArgumentUsage((arg as Extract).arg1, aligned);

			else if (arg is AbstractOperation)
				_tmpAlloc.reportUsage(arg, _operationId, aligned);
		}

	}
}

package aerys.minko.render.shader.compiler.visitor.allocator
{
	import aerys.minko.render.shader.compiler.allocator.Allocator;
	import aerys.minko.render.shader.node.INode;
	import aerys.minko.render.shader.node.leaf.AbstractConstant;
	import aerys.minko.render.shader.node.leaf.Attribute;
	import aerys.minko.render.shader.node.operation.AbstractOperation;
	import aerys.minko.render.shader.node.operation.manipulation.Combine;
	import aerys.minko.render.shader.node.operation.manipulation.Interpolate;
	import aerys.minko.render.shader.node.operation.manipulation.Extract;

	public class VertexAllocator extends AbstractAllocator
	{
		protected var _attrAlloc	: Allocator;

		protected var _visited		: Vector.<INode>;
		protected var _stack		: Vector.<INode>;

		public function VertexAllocator(attrAlloc	: Allocator,
										tmpAlloc	: Allocator,
										constAlloc	: Allocator)
		{
			_operationId = 0;

			_attrAlloc		= attrAlloc;
			_tmpAlloc		= tmpAlloc;
			_constAlloc		= constAlloc;

			_visited		= new Vector.<INode>();
			_stack			= new Vector.<INode>();
		}

		public function processVertexShader(nodes:Vector.<INode>):void
		{
			for each (var node:INode in nodes)
				visit(node);
		}

		override public function visit(shaderNode : INode):void
		{
			if (_visited.indexOf(shaderNode) !== -1)
				return;

			_visited.push(shaderNode);
			_stack.push(shaderNode);

			shaderNode.accept(this);

			if (shaderNode is Interpolate)
			{
				++_operationId;
				reportOperationArgumentsUsage(AbstractOperation(shaderNode));
			}
			else if (shaderNode is Extract)
			{
				reportOperationArgumentsUsage(AbstractOperation(shaderNode));
			}
			else if (shaderNode is Combine)
			{
				var combineNode : Combine = shaderNode as Combine;

				++_operationId;
				reportArgumentUsage(combineNode.arg1, false);

				_tmpAlloc.allocate(combineNode, _operationId);

				++_operationId;
				reportArgumentUsage(combineNode.arg2, false);
			}
			else if (shaderNode is AbstractOperation)
			{
				var operationNode : AbstractOperation = AbstractOperation(shaderNode);

				++_operationId;
				reportOperationArgumentsUsage(operationNode);

				// on ne traite pas le noeud final.
				if (_stack.length > 1)
					_tmpAlloc.allocate(operationNode, _operationId);
			}

			else if (shaderNode is Attribute)
				_attrAlloc.allocate(shaderNode);

			else if (shaderNode is AbstractConstant)
				_constAlloc.allocate(shaderNode);

			_stack.pop();
		}

		override protected function reportArgumentUsage(arg:INode, aligned : Boolean) : void
		{
			if (arg is Attribute)
				_attrAlloc.reportUsage(arg, _operationId, aligned);

			else if (arg is AbstractConstant)
				_constAlloc.reportUsage(arg, _operationId, aligned);

			else if (arg is Extract)
				reportArgumentUsage((arg as Extract).arg1, aligned);

			else if (arg is AbstractOperation)
				_tmpAlloc.reportUsage(arg, _operationId, aligned);
		}

	}
}

Change numerotation system for operations in VertexAllocator. Allows to display a more pertinent debug information if needed.


//
// Flump - Copyright 2012 Three Rings Design

package flump.xfl {

import flash.geom.Matrix;
import flash.geom.Point;

import flump.mold.KeyframeMold;

import com.threerings.util.XmlUtil;

public class XflKeyframe
{
    use namespace xflns;

    public static function parse (lib :XflLibrary, baseLocation :String, xml :XML,
        flipbook :Boolean) :KeyframeMold {

        const kf :KeyframeMold = new KeyframeMold();
        kf.index = XmlUtil.getIntAttr(xml, "index");
        const location :String = baseLocation + ":" + kf.index;
        kf.duration = XmlUtil.getNumberAttr(xml, "duration", 1);
        kf.label = XmlUtil.getStringAttr(xml, "name", null);
        kf.ease = XmlUtil.getNumberAttr(xml, "acceleration", 0) / 100;

        if (flipbook) return kf;
        var symbolXml :XML;
        for each (var frameEl :XML in xml.elements.elements()) {
            if (frameEl.name().localName == "DOMSymbolInstance") {
                if (symbolXml != null)  {
                    lib.addError(location, ParseError.CRIT, "There can be only one symbol instance at " +
                        "a time in a keyframe.");
                } else symbolXml = frameEl;
            } else {
                lib.addError(location, ParseError.CRIT, "Non-symbols may not be in movie layers");
            }
        }

        if (symbolXml == null) return kf; // Purely labelled frame

        if (XmlUtil.getBooleanAttr(xml, "motionTweenOrientToPath", false)) {
            lib.addError(location, ParseError.CRIT, "motion paths are not supported");
        }

        if (XmlUtil.getBooleanAttr(xml, "hasCustomEase", false)) {
            lib.addError(location, ParseError.WARN, "Custom easing is not supported");
        }

        // Fill this in with the library name for now. XflLibrary.finishLoading will swap in the
        // symbol or implicit symbol the library item corresponds to.
        kf.ref = XmlUtil.getStringAttr(symbolXml, "libraryItemName");
        kf.visible = XmlUtil.getBooleanAttr(symbolXml, "isVisible", true);

        var matrix :Matrix = new Matrix();

        // Read the matrix transform
        if (symbolXml.matrix != null) {
            const matrixXml :XML = symbolXml.matrix.Matrix[0];
            function m (name :String, def :Number) :Number {
                return matrixXml == null ? def : XmlUtil.getNumberAttr(matrixXml, name, def);
            }
            matrix = new Matrix(m("a", 1), m("b", 0), m("c", 0), m("d", 1), m("tx", 0), m("ty", 0));

            // Back out of translation
            var rewound :Matrix = matrix.clone();
            rewound.tx = rewound.ty = 0;

            var p :Point = rewound.transformPoint(new Point(1, 0));
            kf.rotation = Math.atan2(p.y, p.x);

            // Back out of rotation
            rewound.rotate(-kf.rotation);

            p = rewound.transformPoint(new Point(1, 1));
            kf.scaleX = p.x;
            kf.scaleY = p.y;

            const skewX :Number = Math.atan(rewound.c);
            const skewY :Number = Math.atan(rewound.b);
            if (Math.abs(skewX) > 0.0001 || Math.abs(skewY) > 0.0001) {
                lib.addError(location, ParseError.WARN, "Skewing is not supported");
            }
        }

        // Read the pivot point
        if (symbolXml.transformationPoint != null) {
            var pivotXml :XML = symbolXml.transformationPoint.Point[0];
            if (pivotXml != null) {
                kf.pivotX = XmlUtil.getNumberAttr(pivotXml, "x", 0);
                kf.pivotY = XmlUtil.getNumberAttr(pivotXml, "y", 0);

                // Translate to the pivot point
                const orig :Matrix = matrix.clone();
                matrix.identity();
                matrix.translate(kf.pivotX, kf.pivotY);
                matrix.concat(orig);
            }
        }

        // Now that the matrix and pivot point have been read, apply translation
        kf.x = matrix.tx;
        kf.y = matrix.ty;

        // Read the alpha
        if (symbolXml.color != null) {
            const colorXml :XML = symbolXml.color.Color[0];
            if (colorXml != null) {
                kf.alpha = XmlUtil.getNumberAttr(colorXml, "alphaMultiplier", 1);
            }
        }
        return kf;
    }
}
}

//
// Flump - Copyright 2012 Three Rings Design

package flump.xfl {

import flash.geom.Matrix;
import flash.geom.Point;

import flump.mold.KeyframeMold;

import com.threerings.util.XmlUtil;

public class XflKeyframe
{
    use namespace xflns;

    public static function parse (lib :XflLibrary, baseLocation :String, xml :XML,
        flipbook :Boolean) :KeyframeMold {

        const kf :KeyframeMold = new KeyframeMold();
        kf.index = XmlUtil.getIntAttr(xml, "index");
        const location :String = baseLocation + ":" + kf.index;
        kf.duration = XmlUtil.getNumberAttr(xml, "duration", 1);
        kf.label = XmlUtil.getStringAttr(xml, "name", null);
        kf.ease = XmlUtil.getNumberAttr(xml, "acceleration", 0) / 100;

        if (flipbook) return kf;
        var symbolXml :XML;
        for each (var frameEl :XML in xml.elements.elements()) {
            if (frameEl.name().localName == "DOMSymbolInstance") {
                if (symbolXml != null)  {
                    lib.addError(location, ParseError.CRIT, "There can be only one symbol instance at " +
                        "a time in a keyframe.");
                } else symbolXml = frameEl;
            } else {
                lib.addError(location, ParseError.CRIT, "Non-symbols may not be in movie layers");
            }
        }

        if (symbolXml == null) return kf; // Purely labelled frame

        if (XmlUtil.getBooleanAttr(xml, "motionTweenOrientToPath", false)) {
            lib.addError(location, ParseError.WARN, "motion paths are not supported");
        }

        if (XmlUtil.getBooleanAttr(xml, "hasCustomEase", false)) {
            lib.addError(location, ParseError.WARN, "Custom easing is not supported");
        }

        // Fill this in with the library name for now. XflLibrary.finishLoading will swap in the
        // symbol or implicit symbol the library item corresponds to.
        kf.ref = XmlUtil.getStringAttr(symbolXml, "libraryItemName");
        kf.visible = XmlUtil.getBooleanAttr(symbolXml, "isVisible", true);

        var matrix :Matrix = new Matrix();

        // Read the matrix transform
        if (symbolXml.matrix != null) {
            const matrixXml :XML = symbolXml.matrix.Matrix[0];
            function m (name :String, def :Number) :Number {
                return matrixXml == null ? def : XmlUtil.getNumberAttr(matrixXml, name, def);
            }
            matrix = new Matrix(m("a", 1), m("b", 0), m("c", 0), m("d", 1), m("tx", 0), m("ty", 0));

            // Back out of translation
            var rewound :Matrix = matrix.clone();
            rewound.tx = rewound.ty = 0;

            var p :Point = rewound.transformPoint(new Point(1, 0));
            kf.rotation = Math.atan2(p.y, p.x);

            // Back out of rotation
            rewound.rotate(-kf.rotation);

            p = rewound.transformPoint(new Point(1, 1));
            kf.scaleX = p.x;
            kf.scaleY = p.y;

            const skewX :Number = Math.atan(rewound.c);
            const skewY :Number = Math.atan(rewound.b);
            if (Math.abs(skewX) > 0.0001 || Math.abs(skewY) > 0.0001) {
                lib.addError(location, ParseError.WARN, "Skewing is not supported");
            }
        }

        // Read the pivot point
        if (symbolXml.transformationPoint != null) {
            var pivotXml :XML = symbolXml.transformationPoint.Point[0];
            if (pivotXml != null) {
                kf.pivotX = XmlUtil.getNumberAttr(pivotXml, "x", 0);
                kf.pivotY = XmlUtil.getNumberAttr(pivotXml, "y", 0);

                // Translate to the pivot point
                const orig :Matrix = matrix.clone();
                matrix.identity();
                matrix.translate(kf.pivotX, kf.pivotY);
                matrix.concat(orig);
            }
        }

        // Now that the matrix and pivot point have been read, apply translation
        kf.x = matrix.tx;
        kf.y = matrix.ty;

        // Read the alpha
        if (symbolXml.color != null) {
            const colorXml :XML = symbolXml.color.Color[0];
            if (colorXml != null) {
                kf.alpha = XmlUtil.getNumberAttr(colorXml, "alphaMultiplier", 1);
            }
        }
        return kf;
    }
}
}

make this a warning

make this a warning


; Write some assembly code here.
; Then click 'Assemble and Run' to run it on the P3 simulator.

; For more information check 'About P3JS'.

; Try the Demos ----->  ----->  ----->  ----->  ----->  ----->  ----->  ----->

; This is a very short program that fills the memory with ac5fh!
; Click 'Assemble and Run' to test.

                ORIG    8000h

                MOV     R1, M[PC]
                MOV     M[PC], R1

; How does it work? Why is the value at the address 8000h not ac5fh?

; HINT
;  ||
;  ||
;  \/

; HINT: Notice that ac5fh is the binary code for 'MOV M[PC], R1'.

; Write some assembly code here.
; Then click 'Assemble and Run' to run it on the P3 simulator.
; Comments start with ';'.

; For more information check 'About P3JS'.

; ------------- ;
; Try the Demos ----->  ----->  ----->  ----->  ----->  ----->  ----->  ----->
; ------------- ;

; This is a simple program that counts to ffffh and shows the result in binary
; on the LEDS.

; Click 'Assemble and Run' then check the tab 'Input/Output'.

LEDS            EQU     fff8h           ; constant with the I/O address to
                                        ; control the LEDS

                ORIG    0000h           ; indication that we want to put the
                                        ; code at position 0000h

                ; the CPU starts running code at the address 0000h
                ; the first instruction is to jump to the Main code

                JMP     Main            ; jump to the Main code

                ; this next code is a simple delay routine
                ; uses R7 to count to 0000h then returns, this is not the ideal
                ; way to make delays, you should use the timer and interrupts

Delay:          MOV     R7, f000h       ; initialize R7 with f000h
DelayInc:       INC     R7              ; increment R7
                BR.NZ   DelayInc        ; if R7 is not 0000h, jump to DelayInc
                RET                     ; else return from the routine

                ; the Main code starts here

Main:           MOV     R1, R0          ; initialize R1 with 0 (R0 is always 0)
Loop:           INC     R1              ; increment R1
                MOV     M[LEDS], R1     ; write the value of R1 to the LEDS
                CALL    Delay           ; call the Delay routine
                BR      Loop            ; branch jump back to Loop

Improve the 'welcome.as' demo to include a proper simple program


/*
 *  FRESteamWorks.as
 *  This file is part of FRESteamWorks.
 *
 *  Created by David ´Oldes´ Oliva on 3/29/12.
 *  Contributors: Ventero <http://github.com/Ventero>
 *  Copyright (c) 2012 Amanita Design. All rights reserved.
 *  Copyright (c) 2012-2013 Level Up Labs, LLC. All rights reserved.
 */

package com.amanitadesign.steam
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.StatusEvent;
	import flash.external.ExtensionContext;
	import flash.utils.ByteArray;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;

	public class FRESteamWorks extends EventDispatcher
	{
		[Event(name="steam_response", type="com.amanitadesign.steam.SteamEvent")]

		private var _ExtensionContext:ExtensionContext;
		private var _tm:int;

		public var isReady:Boolean = false;

		public function FRESteamWorks(target:IEventDispatcher=null)
		{
			_ExtensionContext = ExtensionContext.createExtensionContext("com.amanitadesign.steam.FRESteamWorks", null);
			_ExtensionContext.addEventListener(StatusEvent.STATUS, handleStatusEvent);
			super(target);
		}

		private function handleStatusEvent(event:StatusEvent):void{
			//_ExtensionContext.removeEventListener(StatusEvent.STATUS, handleStatusEvent);
			var req_type:int = new int(event.code);
			var response:int = new int(event.level);
			var sEvent:SteamEvent = new SteamEvent(SteamEvent.STEAM_RESPONSE, req_type, response);
			trace("handleStatusEvent: "+req_type+" "+response);
			dispatchEvent(sEvent);
		}

		public function dispose():void
		{
			clearInterval(_tm);
			_ExtensionContext.removeEventListener(StatusEvent.STATUS, handleStatusEvent);
			_ExtensionContext.dispose();
		}

		public function init():Boolean
		{
			isReady = _ExtensionContext.call("AIRSteam_Init") as Boolean;
			if(isReady)	_tm = setInterval(runCallbacks, 100);
			return isReady;
		}
		public function requestStats():Boolean
		{
			return _ExtensionContext.call("AIRSteam_RequestStats") as Boolean;
		}

		public function runCallbacks():Boolean
		{
			return _ExtensionContext.call("AIRSteam_RunCallbacks") as Boolean;
		}

		public function getUserID():String
		{
			return _ExtensionContext.call("AIRSteam_GetUserID") as String;
		}

		public function getPersonaName():String
		{
			return _ExtensionContext.call("AIRSteam_GetPersonaName") as String;
		}

		public function useCrashHandler():Boolean
		{
			return _ExtensionContext.call("AIRSteam_UseCrashHandler") as Boolean;
		}

		public function setAchievement(id:String):Boolean
		{
			return _ExtensionContext.call("AIRSteam_SetAchievement", id) as Boolean;
		}

		public function clearAchievement(id:String):Boolean
		{
			return _ExtensionContext.call("AIRSteam_ClearAchievement", id) as Boolean;
		}

		public function isAchievement(id:String):Boolean
		{
			return _ExtensionContext.call("AIRSteam_IsAchievement", id) as Boolean;
		}

		public function getStatInt(id:String):int
		{
			return _ExtensionContext.call("AIRSteam_GetStatInt", id) as int;
		}

		public function getStatFloat(id:String):Number
		{
			return _ExtensionContext.call("AIRSteam_GetStatFloat", id) as Number;
		}

		public function setStatInt(id:String, value:int):Boolean
		{
			return _ExtensionContext.call("AIRSteam_SetStatInt", id, value) as Boolean;
		}

		public function setStatFloat(id:String, value:Number):Boolean
		{
			return _ExtensionContext.call("AIRSteam_SetStatFloat", id, value) as Boolean;
		}

		public function storeStats():Boolean
		{
			return _ExtensionContext.call("AIRSteam_StoreStats") as Boolean;
		}

		public function resetAllStats(bAchievementsToo:Boolean):Boolean
		{
			return _ExtensionContext.call("AIRSteam_ResetAllStats", bAchievementsToo) as Boolean;
		}

		public function getFileCount():int
		{
			return _ExtensionContext.call("AIRSteam_GetFileCount") as int;
		}

		public function getFileSize(fileName:String):int
		{
			return _ExtensionContext.call("AIRSteam_GetFileSize", fileName) as int;
		}

		public function fileExists(fileName:String):Boolean
		{
			return _ExtensionContext.call("AIRSteam_FileExists", fileName) as Boolean;
		}

		public function fileWrite(fileName:String, data:ByteArray):Boolean
		{
			return _ExtensionContext.call("AIRSteam_FileWrite", fileName, data) as Boolean;
		}

		public function fileRead(fileName:String, data:ByteArray):Boolean
		{
			return _ExtensionContext.call("AIRSteam_FileRead", fileName, data) as Boolean;
		}

		public function fileDelete(fileName:String):Boolean
		{
			return _ExtensionContext.call("AIRSteam_FileDelete", fileName) as Boolean;
		}

		public function isCloudEnabledForApp():Boolean
		{
			return _ExtensionContext.call("AIRSteam_IsCloudEnabledForApp") as Boolean;
		}

		public function setCloudEnabledForApp(enabled:Boolean):Boolean
		{
			return _ExtensionContext.call("AIRSteam_SetCloudEnabledForApp", enabled) as Boolean;
		}
	}
}

/*
 *  FRESteamWorks.as
 *  This file is part of FRESteamWorks.
 *
 *  Created by David ´Oldes´ Oliva on 3/29/12.
 *  Contributors: Ventero <http://github.com/Ventero>
 *  Copyright (c) 2012 Amanita Design. All rights reserved.
 *  Copyright (c) 2012-2013 Level Up Labs, LLC. All rights reserved.
 */

package com.amanitadesign.steam
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.StatusEvent;
	import flash.external.ExtensionContext;
	import flash.utils.ByteArray;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;

	public class FRESteamWorks extends EventDispatcher
	{
		[Event(name="steam_response", type="com.amanitadesign.steam.SteamEvent")]

		private var _ExtensionContext:ExtensionContext;
		private var _tm:int;

		public var isReady:Boolean = false;

		public function FRESteamWorks(target:IEventDispatcher=null)
		{
			_ExtensionContext = ExtensionContext.createExtensionContext("com.amanitadesign.steam.FRESteamWorks", null);
			_ExtensionContext.addEventListener(StatusEvent.STATUS, handleStatusEvent);
			super(target);
		}

		private function handleStatusEvent(event:StatusEvent):void{
			//_ExtensionContext.removeEventListener(StatusEvent.STATUS, handleStatusEvent);
			var req_type:int = new int(event.code);
			var response:int = new int(event.level);
			var sEvent:SteamEvent = new SteamEvent(SteamEvent.STEAM_RESPONSE, req_type, response);
			trace("handleStatusEvent: "+req_type+" "+response);
			dispatchEvent(sEvent);
		}

		public function dispose():void
		{
			clearInterval(_tm);
			_ExtensionContext.removeEventListener(StatusEvent.STATUS, handleStatusEvent);
			_ExtensionContext.dispose();
		}

		public function init():Boolean
		{
			isReady = _ExtensionContext.call("AIRSteam_Init") as Boolean;
			if(isReady)	_tm = setInterval(runCallbacks, 100);
			return isReady;
		}
		public function requestStats():Boolean
		{
			return _ExtensionContext.call("AIRSteam_RequestStats") as Boolean;
		}

		public function runCallbacks():Boolean
		{
			return _ExtensionContext.call("AIRSteam_RunCallbacks") as Boolean;
		}

		public function getUserID():String
		{
			return _ExtensionContext.call("AIRSteam_GetUserID") as String;
		}

		public function getPersonaName():String
		{
			return _ExtensionContext.call("AIRSteam_GetPersonaName") as String;
		}

		public function useCrashHandler(version:String, date:String, time:String):Boolean
		{
			return _ExtensionContext.call("AIRSteam_UseCrashHandler", version, date, time) as Boolean;
		}

		public function setAchievement(id:String):Boolean
		{
			return _ExtensionContext.call("AIRSteam_SetAchievement", id) as Boolean;
		}

		public function clearAchievement(id:String):Boolean
		{
			return _ExtensionContext.call("AIRSteam_ClearAchievement", id) as Boolean;
		}

		public function isAchievement(id:String):Boolean
		{
			return _ExtensionContext.call("AIRSteam_IsAchievement", id) as Boolean;
		}

		public function getStatInt(id:String):int
		{
			return _ExtensionContext.call("AIRSteam_GetStatInt", id) as int;
		}

		public function getStatFloat(id:String):Number
		{
			return _ExtensionContext.call("AIRSteam_GetStatFloat", id) as Number;
		}

		public function setStatInt(id:String, value:int):Boolean
		{
			return _ExtensionContext.call("AIRSteam_SetStatInt", id, value) as Boolean;
		}

		public function setStatFloat(id:String, value:Number):Boolean
		{
			return _ExtensionContext.call("AIRSteam_SetStatFloat", id, value) as Boolean;
		}

		public function storeStats():Boolean
		{
			return _ExtensionContext.call("AIRSteam_StoreStats") as Boolean;
		}

		public function resetAllStats(bAchievementsToo:Boolean):Boolean
		{
			return _ExtensionContext.call("AIRSteam_ResetAllStats", bAchievementsToo) as Boolean;
		}

		public function getFileCount():int
		{
			return _ExtensionContext.call("AIRSteam_GetFileCount") as int;
		}

		public function getFileSize(fileName:String):int
		{
			return _ExtensionContext.call("AIRSteam_GetFileSize", fileName) as int;
		}

		public function fileExists(fileName:String):Boolean
		{
			return _ExtensionContext.call("AIRSteam_FileExists", fileName) as Boolean;
		}

		public function fileWrite(fileName:String, data:ByteArray):Boolean
		{
			return _ExtensionContext.call("AIRSteam_FileWrite", fileName, data) as Boolean;
		}

		public function fileRead(fileName:String, data:ByteArray):Boolean
		{
			return _ExtensionContext.call("AIRSteam_FileRead", fileName, data) as Boolean;
		}

		public function fileDelete(fileName:String):Boolean
		{
			return _ExtensionContext.call("AIRSteam_FileDelete", fileName) as Boolean;
		}

		public function isCloudEnabledForApp():Boolean
		{
			return _ExtensionContext.call("AIRSteam_IsCloudEnabledForApp") as Boolean;
		}

		public function setCloudEnabledForApp(enabled:Boolean):Boolean
		{
			return _ExtensionContext.call("AIRSteam_SetCloudEnabledForApp", enabled) as Boolean;
		}
	}
}

Add missing arguments for useCrashHandler