<?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.containers.View3D;
            import away3d.core.math.Number3D;
            import away3d.core.utils.Cast;
            import away3d.extrusions.Elevation;
            import away3d.materials.BitmapMaterial;
            import away3d.materials.WireColorMaterial;
            
            import com.greensock.*;
            import com.greensock.easing.*;
            
            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_SIZE:Number = 256;
            private var SUBDIVISION_SIZE:Number = 20;
            private var ELEVATION_HEIGHT:Number = 0.05;
            private var DO_RIPPLE:Boolean = true;
            [Embed("water.jpg")] private var waterImage:Class;
            
            private var _elevation:Elevation;
            private var _extrude:SavageLookSkinExtrude = null;
            private var _heightData:BitmapData = new BitmapData(HEIGHTMAP_SIZE,HEIGHTMAP_SIZE);
            private var _bmDisplay:Bitmap;            
            public var _heightX:Number = 0;

            private var heightMapSprite:Sprite = new Sprite();
            private var matrix:Matrix = new Matrix();
            private var waterMaterial:BitmapMaterial = new BitmapMaterial(Cast.bitmap(waterImage));
            private var wireMaterial:WireColorMaterial = new WireColorMaterial(0x000000, {wireColor:0xffffff});
            private var verts:Array = new Array();
            
            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 = "";
                away3dMain.view.camera.position = new Number3D(0, 80, -400);
                away3dMain.view.camera.lookAt(new Number3D(0,-200,0));
                away3dMain.view.camera.focus *= 2;
                ui.addChild(away3dMain.view);
                this.addElementAt(ui,1);
                
                // setup height map
                _elevation = new Elevation();
                _heightData = new BitmapData(HEIGHTMAP_SIZE, HEIGHTMAP_SIZE);
                _createHeightData();
                _createSkinExtrude();
                
                // bitmap 
                _bmDisplay = new Bitmap();
                _bmDisplay.x = 700;
                _bmDisplay.scaleX = _bmDisplay.scaleY = 100.0 / Number(HEIGHTMAP_SIZE);
                _bmDisplay.filters = [new BevelFilter()];
                ui.addChild(_bmDisplay);
                
                // tween scene
                var tw:TweenLite = new TweenLite(this, 5, {_heightX:255, 
                    ease:Linear.easeOut,
                    onComplete:function():void { tw.reverse(); },
                    onReverseComplete:function():void { DO_RIPPLE = !DO_RIPPLE; tw.play(); }
                }
                );
                
                away3dMain.preRender = function():void { 
                    _createHeightData();
                    _bmDisplay.bitmapData = _heightData;
                    verts = _elevation.generate(_heightData,"r",SUBDIVISION_SIZE,SUBDIVISION_SIZE,1,1,ELEVATION_HEIGHT);
                    _extrude.generate(verts, 1, true, false, false, false);
                    _extrude.y = -150 - ((ELEVATION_HEIGHT - 0.05) * HEIGHTMAP_SIZE);
                };
                away3dMain.postRender = function():void { trace("postRender"); };
            }
            
            private function _createHeightData():void {
                heightMapSprite.graphics.clear();
                if (DO_RIPPLE) {
                    matrix.createGradientBox(HEIGHTMAP_SIZE+_heightX*2,HEIGHTMAP_SIZE+_heightX*2,0,-_heightX,-_heightX);
                    heightMapSprite.graphics.beginGradientFill("radial", 
                        [0xffffff,0x000000,0xffffff,0x000000,0xffffff,0x000000,0xffffff], 
                        [1,1,1,1,1,1,1], 
                        [0,_heightX/6,_heightX/3,_heightX/2,_heightX*2/3,_heightX*5/6,_heightX], 
                        matrix,SpreadMethod.PAD);
                } else {
                    matrix.createGradientBox(HEIGHTMAP_SIZE, HEIGHTMAP_SIZE, 0, _heightX, 0);
                    heightMapSprite.graphics.beginGradientFill("linear",
                        [0xffffff,0x888888, 0x000000,0x888888, 0xffffff], 
                        [1,1,1,1,1], 
                        [0,_heightX/6,_heightX/2, _heightX*5/6,_heightX], 
                        matrix,SpreadMethod.PAD);
                }
                heightMapSprite.graphics.drawRect(0,0,HEIGHTMAP_SIZE,HEIGHTMAP_SIZE);
                heightMapSprite.graphics.endFill();
                _heightData.draw(heightMapSprite);
            }
            
            private function _createSkinExtrude():void {
                _extrude = new SavageLookSkinExtrude(_elevation.generate(_heightData,"r",SUBDIVISION_SIZE,SUBDIVISION_SIZE,1,1,ELEVATION_HEIGHT),
                    {coverall:true, recenter:false});
                _extrude.rotationX = 90;
                _extrude.material = waterMaterial;
                _extrude.position = new Number3D(-_extrude.objectWidth/2, -_extrude.objectHeight/2, -_extrude.objectDepth/2);
                _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 {
                    _extrude.material = waterMaterial;
                }
            }


            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;
            }

        ]]>
    </fx:Script>
    <local:Away3dUIComponent id="away3dMain" chromeColor="#000000"/>
    <s:CheckBox x="156" y="10" label="Show Wireframe" click="checkbox1_clickHandler(event)" color="#FFFFFF"/>
    <s:HSlider x="412" y="15" width="177" id="elevationSlider" minimum="0.05" maximum="0.25" stepSize="0.05" value="0.05" change="elevationSlider_changeHandler(event)"/>
    <s:HSlider x="413" y="34" width="177" id="divisionSlider" minimum="20" maximum="100" stepSize="5" value="20" change="divisionSlider_changeHandler(event)"/>
    <s:Label x="291" y="15" text="Elevation Height" width="113" color="#FFFFFF"/>
    <s:Label x="291" y="35" 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:Application>