package {    
    
    /**
     * 
     *     Auteur: Vincent Helwig
     *     Date: 02.10.2008
     *     Website: http://www.tsoin.com
     *     Description: Démo Away3D Box / Sphere / Plane / Cone
     *                         Gestion Filaire / Texture
     *                         Smooth
     * 
     **/

    import away3d.cameras.Camera3D;
    import away3d.containers.ObjectContainer3D;
    import away3d.containers.Scene3D;
    import away3d.containers.View3D;
    import away3d.core.utils.Cast;
    import away3d.materials.BitmapMaterial;
    import away3d.materials.WireframeMaterial;
    import away3d.primitives.AbstractPrimitive;
    import away3d.primitives.Cone;
    import away3d.primitives.Cube;
    import away3d.primitives.Plane;
    import away3d.primitives.Sphere;
    
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import flash.utils.getTimer;
    
    import net.hires.utils.Stats;
    
    [SWF(backgroundColor="#000000", frameRate="100", width="600", height="400")]
    
    public class Away3D_004 extends Sprite    {
        
        private var scene:Scene3D;
        private var camera:Camera3D;
        private var view:View3D;
        private var objectContainer:ObjectContainer3D;
        private var cube:Cube;
        private var plane:Plane;
        private var sphere:Sphere;
        private var cone:Cone;
        private var currentPrimitive:AbstractPrimitive;        
        private var _textFaces:TextField;
        private var _tempsCreation:uint;
        
        private var _texture:Boolean = false;
        private var _smoothTexture:Boolean = false;
        private var _numSegments:uint = 3;
        private var currentPrimitiveName:String = "cube";
        
        // Nombre de faces minimum pour chaque Object 3D
        private static const MIN_FACES_BOX:uint = 3;
        private static const MIN_FACES_SPHERE:uint = 8;
        private static const MIN_FACES_PLANE:uint = 3;
        private static const MIN_FACES_CONE:uint = 6;
        // Coordonnée Z maximum de la camera
        private static const MAX_Z:int = -200;
        private static const TEXT_EXPLICATION:String = "" + 
                "Utiliser la molette pour modifier la coordonée z de la camera<br>" + 
                "Action du clavier : <br>" + 
                " + / - : Augmente / Diminue le nombre de segments<br>" + 
                " T / F : Mode texture / Mode filaire<br>" + 
                " L : Active/Désactive le lissage de la texture<br>" + 
                " C / S / P / B : Forme Cone / Sphere / Plane / Box<br><br>";

        [Embed(source="AdobeFlash9.png")]
        private static var _textureImage:Class;
        public static function get textureImage():BitmapData { return Cast.bitmap(_textureImage);     }
        
        public function Away3D_004() {
            addEventListener(Event.ADDED_TO_STAGE, init);
            var __stats:Stats = new Stats();
            __stats.width = 75;
            __stats.x = 525;
            addChild( __stats );
            
            var __textFormat:TextFormat = new TextFormat();
            __textFormat.font = "Arial";
            __textFormat.size = 9;
            
            _textFaces = new TextField();
            _textFaces.selectable = false;
            _textFaces.multiline = true
            _textFaces.width = stage.stageWidth;
            _textFaces.height = stage.stageHeight;
            _textFaces.defaultTextFormat = __textFormat;
            _textFaces.textColor = 0x999999;
            addChild( _textFaces );
        }
        
        private function init(event:Event):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            
            setupScene();
            
            numSegments = _numSegments;
            
            stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
            stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);

        }
        
        private function setupScene():void {
            
            scene = new Scene3D();
            camera = new Camera3D({zoom: 10, focus: 50, x:0, y:0, z:-300});
            
            view = new View3D({scene:scene, camera:camera});
            view.x = stage.stageWidth / 2;
            view.y = stage.stageHeight / 2;
            addChild(view);
            
            createPrimitive();

        }
        
        /**
         * 
         *     Création de la primivite suivant la valeur de la variable currentPrimitiveName
         * 
         **/
        
        private function createPrimitive():void {
            var __t:Number = getTimer();
            switch ( currentPrimitiveName ) {
                default :
                case "cube" : currentPrimitive = createCube(); break;
                case "sphere" : currentPrimitive = createSphere(); break;
                case "plane" : currentPrimitive = createPlane(); break;
                case "cone" :     currentPrimitive = createCone(); break;
            }
            _tempsCreation = getTimer() - __t;
            if ( _texture ) { currentPrimitive.material =  new BitmapMaterial( textureImage, {precision:1, smooth: _smoothTexture}); }
            else { currentPrimitive.material = new WireframeMaterial(0x789789); }
             numSegments = _numSegments;
            scene.addChild(currentPrimitive);
            
            // On met à jour en fonction de la position de la souris
            onMouseMove();
        }
        
        private function createCube():Cube {
            cube = new Cube({ width:100, height: 100});
            return cube;
        }
        
        private function createSphere():Sphere {
            sphere = new Sphere();
            sphere.segmentsH = sphere.segmentsW = _numSegments;
            return sphere;
        }
        
        private function createPlane():Plane {
            plane = new Plane();
            plane.bothsides = true;
            plane.segmentsH = plane.segmentsW = _numSegments;
            return plane;
        }
        
        private function createCone():Cone {
            cone = new Cone({width: 100, height: 100});
            cone.segmentsH = cone.segmentsW = _numSegments;
            return cone;
        }
        
        private function onEnterFrame(event:Event):void {
            view.render();
        }
        
        private function onMouseMove(event:Event = null):void {
            currentPrimitive.rotationX = ( stage.mouseY * 360 ) / stage.stageHeight - 90;
            currentPrimitive.rotationY = ( stage.mouseX * 360 ) / stage.stageWidth - 90;
        }
        
        private function onKeyDown(event:KeyboardEvent):void {
            var __change:Boolean = true;
            switch ( event.keyCode ) {
                case 107 : // +
                case 187 :// Pavé numérique et "normal"
                    numSegments = _numSegments+1;
                    break;
                case 109 : // - 
                case 54 :    // Pavé  numérique et "normal"
                    if ( _numSegments != 3 ) { numSegments = _numSegments-1; }
                    break;
                case 83 : // Touche S
                    currentPrimitiveName = "sphere";
                    if ( _numSegments < MIN_FACES_SPHERE ) numSegments = MIN_FACES_SPHERE;
                    break;
                case 66 : // Touche B
                    currentPrimitiveName = "box";
                    if ( _numSegments < MIN_FACES_BOX ) numSegments = MIN_FACES_BOX;
                    break;
                case 80 : // Touche P
                    currentPrimitiveName = "plane";
                    if ( _numSegments < MIN_FACES_PLANE ) numSegments = MIN_FACES_PLANE;
                    break;
                case 67 : // Touche C
                    currentPrimitiveName = "cone";
                    if ( _numSegments < MIN_FACES_CONE ) numSegments = MIN_FACES_CONE;
                    break;
                 case 70 : // Touche T
                     _texture = false;
                     break;
                 case 84 : // Touche M
                     _texture = true;
                     break;
                 case 76 : // Touche L
                     _smoothTexture = !_smoothTexture;
                     break;
                default : // Si aucune touche ne correspond à celle qu'on écoute, on passe la variable __change false
                __change = false;
                trace(event.keyCode);
            }
            // Si la touche tapée correspond à une touche écouté, on met à jour le moteur 3D
            if (__change) {
                if ( currentPrimitive.parent != null) { scene.removeChild( currentPrimitive ); }
                createPrimitive();
            }
        }
                
        /**
         *
         *     Action de la molette de la souris
         *      On modifie la coordonnée z de la camera
         * 
         **/
        private function onMouseWheel(event:MouseEvent):void {
            camera.z += event.delta * 10;
            if ( camera.z > MAX_Z) camera.z = MAX_Z;
            numSegments = _numSegments;
        }

        /**
         * 
         *     Setter du nombre de segments
         *     Mise à jour le texte
         * 
         **/
        private function set numSegments(nb:uint):void {
            _numSegments = nb;
            _textFaces.htmlText = TEXT_EXPLICATION + "<b>SegmentsH && segmentsW = </b>" + _numSegments.toString();
            if ( camera != null) { _textFaces.htmlText += "<b>Zoom camera : </b>" + camera.z; }
            if ( currentPrimitive != null) { 
                // _textFaces.htmlText += "<b>Nb segments : </b>" + currentPrimitive.segments.length;
                _textFaces.htmlText += "<b>Nb vertices : </b>" + currentPrimitive.vertices.length; 
            }
           _textFaces.htmlText += "<b>Temps création object3D : </b>" + _tempsCreation + " ms";
           _textFaces.htmlText += "<b>Lissage texture : </b>" + _smoothTexture;

        }

    }
    
}