<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" 
               width="800" height="600" frameRate="60"
               creationComplete="_onCreationComplete();" xmlns:local="*" viewSourceURL="srcview/index.html">
    <fx:Script>
        <![CDATA[
            import away3d.cameras.HoverCamera3D;
            import away3d.containers.View3D;
            import away3d.core.utils.Cast;
            import away3d.extrusions.Elevation;
            import away3d.lights.DirectionalLight3D;
            import away3d.materials.BitmapMaterial;
            import away3d.materials.ShadingColorMaterial;
            import away3d.materials.WireColorMaterial;
            
            import flash.display.Bitmap;
            import flash.display.BitmapData;
            import flash.display.Sprite;
            import flash.display.StageQuality;
            import flash.events.Event;
            import flash.filters.BevelFilter;
            import flash.geom.Matrix;
            
            import mx.core.UIComponent;
            
            private var HEIGHTMAP_WIDTH:Number = 256;
            private var HEIGHTMAP_HEIGHT:Number = 256;
            private var SUBDIVISION_SIZE:Number = 20;
            private var ELEVATION_HEIGHT:Number = 0.05;
            private var TRANSITION_SPEED:Number = 0.02;
            
            [Embed("hm1.jpg")] private var hm1Image:Class;
            [Embed("hm2.jpg")] private var hm2Image:Class;
            [Embed("letters/s.jpg")] private var letterSImage:Class;
            [Embed("letters/a.jpg")] private var letterAImage:Class;
            [Embed("letters/v.jpg")] private var letterVImage:Class;
            [Embed("letters/g.jpg")] private var letterGImage:Class;
            [Embed("letters/e.jpg")] private var letterEImage:Class;
            [Embed("letters/l.jpg")] private var letterLImage:Class;
            [Embed("letters/o.jpg")] private var letterOImage:Class;
            [Embed("letters/k.jpg")] private var letterKImage:Class;
            [Embed("terrain.jpg")] private var terrainImage:Class;
            
            private var _hm1Bitmap:Bitmap = new Bitmap(Cast.bitmap(hm1Image));
            private var _hm2Bitmap:Bitmap = new Bitmap(Cast.bitmap(hm2Image));
            private var _letterSBitmap:Bitmap = new Bitmap(Cast.bitmap(letterSImage));
            private var _letterABitmap:Bitmap = new Bitmap(Cast.bitmap(letterAImage));
            private var _letterVBitmap:Bitmap = new Bitmap(Cast.bitmap(letterVImage));
            private var _letterA2Bitmap:Bitmap = new Bitmap(Cast.bitmap(letterAImage));
            private var _letterGBitmap:Bitmap = new Bitmap(Cast.bitmap(letterGImage));
            private var _letterEBitmap:Bitmap = new Bitmap(Cast.bitmap(letterEImage));
            private var _letterLBitmap:Bitmap = new Bitmap(Cast.bitmap(letterLImage));
            private var _letterOBitmap:Bitmap = new Bitmap(Cast.bitmap(letterOImage));
            private var _letterO2Bitmap:Bitmap = new Bitmap(Cast.bitmap(letterOImage));
            private var _letterKBitmap:Bitmap = new Bitmap(Cast.bitmap(letterKImage));

            private var _camera:HoverCamera3D;
            private var _elevation:Elevation;
            private var _extrude:SavageLookSkinExtrude = null;
            private var _heightData:BitmapData = new BitmapData(HEIGHTMAP_WIDTH,HEIGHTMAP_HEIGHT);
            private var _bmDisplay:Bitmap;            
            public var _overlayAlpha:Number = 1.0;

            private var heightMapSprite:Sprite = new Sprite();
            private var matrix:Matrix = new Matrix();
            private var terrainMaterial:BitmapMaterial = new BitmapMaterial(Cast.bitmap(terrainImage));
            private var shadingMaterial:ShadingColorMaterial = new ShadingColorMaterial(0xbbbbbb);
            private var wireMaterial:WireColorMaterial = new WireColorMaterial(0x000000, {wireColor:0xffffff});
            private var verts:Array = new Array();
            
            private var _changedMesh:Boolean = false;
            
            private function _onCreationComplete():void {
                if (stage) {
                    _init();
                } else {
                    this.addEventListener(Event.ADDED_TO_STAGE, function(e:Event):void { _init(); } );
                }
            }
            
            private function _init():void {
                var ui:UIComponent = new UIComponent();
                
                stage.quality = flash.display.StageQuality.LOW;
                _drawBackground();
                
                // setup view
                away3dMain.title = "";
                _camera = new HoverCamera3D({panAngle:180, tiltAngle:15,  distance:250});
                away3dMain.view.camera = _camera;
                _camera.hover(true);
                
                var light:DirectionalLight3D = new DirectionalLight3D();
                light.direction = new Vector3D(400,-300,200);
                away3dMain.view.scene.addLight(light);
                ui.addChild(away3dMain.view);
                this.addElementAt(ui,1);
                
                // setup height map
                _elevation = new Elevation();
                _heightData = new BitmapData(HEIGHTMAP_WIDTH, HEIGHTMAP_HEIGHT);
                
                // create height data
                heightMapSprite = new Sprite();
                heightMapSprite.addChild(_hm1Bitmap);
                heightMapSprite.addChild(_hm2Bitmap);
                _heightData.draw(heightMapSprite);
                
                // create skin extrusion
                _createSkinExtrude();
                
                // bitmap 
                _bmDisplay = new Bitmap();
                _bmDisplay.x = 700;
                _bmDisplay.scaleX = 100.0 / Number(HEIGHTMAP_WIDTH);
                _bmDisplay.scaleY = 100.0 / Number(HEIGHTMAP_HEIGHT);
                _bmDisplay.filters = [new BevelFilter()];
                ui.addChild(_bmDisplay);

                away3dMain.preRender = function():void { 
                    _camera.hover();
                    _overlayAlpha -= TRANSITION_SPEED;
                    
                    if (_changedMesh) {
                        while(heightMapSprite.numChildren > 0) { heightMapSprite.removeChildAt(0); }
                        if (terrainRadioButton.selected) {
                            heightMapSprite.addChild(_hm1Bitmap);
                            heightMapSprite.addChild(_hm2Bitmap);
                            TRANSITION_SPEED = TRANSITION_SPEED / 2;
                        } else {
                            heightMapSprite.addChild(_letterKBitmap);
                            heightMapSprite.addChild(_letterO2Bitmap);
                            heightMapSprite.addChild(_letterOBitmap);
                            heightMapSprite.addChild(_letterLBitmap);
                            heightMapSprite.addChild(_letterEBitmap);
                            heightMapSprite.addChild(_letterGBitmap);
                            heightMapSprite.addChild(_letterA2Bitmap);
                            heightMapSprite.addChild(_letterVBitmap);
                            heightMapSprite.addChild(_letterABitmap);
                            heightMapSprite.addChild(_letterSBitmap);
                            TRANSITION_SPEED = TRANSITION_SPEED * 2;
                        }
                        _changedMesh = false;
                    }
                    
                    var child:Bitmap = heightMapSprite.getChildAt(heightMapSprite.numChildren-1) as Bitmap;
                    child.alpha = _overlayAlpha;
                    if (child.alpha <= 0) {
                        heightMapSprite.setChildIndex(child, 0);
                        child.alpha = 1;
                        _overlayAlpha = 2;
                    }
                    
                    _heightData.draw(heightMapSprite);
                    _bmDisplay.bitmapData = _heightData;
                    
                    verts = _elevation.generate(_heightData,"r",SUBDIVISION_SIZE,SUBDIVISION_SIZE,1,1,ELEVATION_HEIGHT);
                    _extrude.generate(verts, 1, true, false, false, false);
                };
                away3dMain.postRender = function():void { trace("postRender"); };
                
                stage.addEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);
            }
            
            private function _onMouseMove(e:MouseEvent):void {
                _camera.panAngle = 180 + ( (e.stageX-(stage.stageWidth/2)) * 60 / (stage.stageWidth/2) );
                if (!terrainRadioButton.selected) {
                    _camera.tiltAngle = -(e.stageY-(stage.stageHeight/2)) * 30 / (stage.stageHeight/2);
                }
            }
            
            private function _createSkinExtrude():void {
                _extrude = new SavageLookSkinExtrude(_elevation.generate(_heightData,"r",SUBDIVISION_SIZE,SUBDIVISION_SIZE,1,1,ELEVATION_HEIGHT),
                    {coverall:true, recenter:false});
                _extrude.material = terrainMaterial;
                _extrude.pivotPoint = new Vector3D(_extrude.objectWidth/2, _extrude.objectHeight/2, 0);
                _extrude.position = new Vector3D(0,0,0);
                _extrude.rotationX = 90;
                _extrude.mouseEnabled = false;
                away3dMain.view.scene.addChild(_extrude);
            }
            
            private function _drawBackground():void {
                var sprite:Sprite = new Sprite();
                var ui:UIComponent = new UIComponent();
                var matrix:Matrix = new Matrix();
                
                matrix.createGradientBox(this.width, this.height, Math.PI/2, 0, 0);
                sprite.graphics.beginGradientFill("linear", [0x222222, 0xffffff, 0x222222], [1,1,1], [0,127,255], matrix);
                sprite.graphics.drawRect(0, 0, this.width, this.height);
                sprite.graphics.endFill();
                ui.addChild(sprite);
                this.addElementAt(ui, 0);
            }

            protected function checkbox1_clickHandler(event:MouseEvent):void
            {
                var cb:CheckBox = event.target as CheckBox;
                if (cb.selected) {
                    _extrude.material = wireMaterial;
                } else {
                    if (terrainRadioButton.selected) {
                        _extrude.material = terrainMaterial;
                    } else {
                        _extrude.material = shadingMaterial;
                    }
                }
            }


            protected function elevationSlider_changeHandler(event:Event):void
            {
                var hs:HSlider = event.target as HSlider;
                ELEVATION_HEIGHT = hs.value;
            }


            protected function divisionSlider_changeHandler(event:Event):void
            {
                var hs:HSlider = event.target as HSlider;
                SUBDIVISION_SIZE = hs.value;
            }


            protected function radiobutton1_clickHandler(event:MouseEvent):void
            {
                // do terrain
                _extrude.rotationX = 90;
                _extrude.material = terrainMaterial;
                _camera.tiltAngle = 15;
                _camera.distance = 250;
                elevationSlider.value = 0.25;
                divisionSlider.value = 20;
                ELEVATION_HEIGHT = elevationSlider.value;
                SUBDIVISION_SIZE = divisionSlider.value;
                _changedMesh = true;
            }


            protected function radiobutton2_clickHandler(event:MouseEvent):void
            {
                // do letters
                _extrude.rotationX = 180;
                _extrude.material = shadingMaterial;
                _camera.tiltAngle = 0;
                _camera.distance = 400;
                elevationSlider.value = 0.1;
                divisionSlider.value = 20;
                ELEVATION_HEIGHT = elevationSlider.value;
                SUBDIVISION_SIZE = divisionSlider.value;
                _changedMesh = true;
            }

        ]]>
    </fx:Script>
    <fx:Declarations>
        <s:RadioButtonGroup id="Mesh"/>
    </fx:Declarations>
    <local:Away3dUIComponent id="away3dMain" chromeColor="#000000"/>
    <s:CheckBox x="156" y="10" label="Show Wireframe" click="checkbox1_clickHandler(event)" color="#FFFFFF"/>
    <s:HSlider x="476" y="17" width="177" id="elevationSlider" minimum="0.05" maximum="0.5" stepSize="0.05" value="0.25" change="elevationSlider_changeHandler(event)"/>
    <s:HSlider x="477" y="36" width="177" id="divisionSlider" minimum="20" maximum="60" stepSize="5" value="20" change="divisionSlider_changeHandler(event)"/>
    <s:Label x="355" y="17" text="Elevation Height" width="113" color="#FFFFFF"/>
    <s:Label x="355" y="37" text="Subdivision Size" width="114" color="#FFFFFF"/>
    <s:Label x="700" y="110" text="Height Map" width="100" textAlign="center" color="#FFFFFF" fontWeight="bold"/>
    <s:RadioButton x="156" y="31" label="Terrain" groupName="Mesh" selected="true" color="#FFFFFF" click="radiobutton1_clickHandler(event)" id="terrainRadioButton"/>
    <s:RadioButton x="232" y="31" label="Letters" groupName="Mesh" selected="false" enabled="true" color="#FFFFFF" click="radiobutton2_clickHandler(event)"/>
</s:Application>