package
{
    import flash.display.*;
    import flash.events.*;
    import flash.filesystem.*;
    import flash.utils.*;
    import flash.filters.*;

    import org.papervision3d.cameras.*;
    import org.papervision3d.materials.*;
    import org.papervision3d.objects.*;
    import org.papervision3d.scenes.*;

    import com.adobe.images.*;

    [SWF(width=450, height=350, backgroundColor=0x000000)]

    public class Pv3dGrapFile extends Sprite
    {
        // _______________________________________________________________________
        //                                                                  vars3D
        private var container : Sprite;
        private var scene     : MovieScene3D;
        private var camera    : Camera3D;
        private var cubeObj:Cube;

        private var planeSize : int = 300;

        private var valx      : Number = 0;
        private var valy      : Number = 0;

        static public const
            TEXTURE_W:int = 240,    ///< テクスチャの幅
            TEXTURE_H:int = 240,    ///< テクスチャの高さ
            SCREEN_W:int = 450,     ///< SWFの幅
            SCREEN_H:int = 350;     ///< SWFの高さ

        // _______________________________________________________________________
        //                                                             Constructor
        public function Pv3dGrapFile():void
        {
            stage.frameRate = 60;
            stage.quality   = "MEDIUM";
            stage.scaleMode = "noScale";
            stage.align = StageAlign.TOP_LEFT;
            this.addEventListener(Event.ENTER_FRAME, loop3D);
            this.stage.addEventListener(Event.RESIZE, onStageResize);

            // ベーススプライト作成。背景色用
            var base:Sprite=new Sprite();
            base.graphics.beginFill(0xB9CCD5);
            base.graphics.drawRect(0,0,SCREEN_W,SCREEN_H);
            base.graphics.endFill();
            addChild(base);

            // ボタンの作成
            var BUTTON_W:int = 90, BUTTON_H:int = 20;
            var jpgButton:TextButton = new TextButton(BUTTON_W, BUTTON_H, "JPG保存");
            jpgButton.x = 10;
            jpgButton.y = 10;
            addChild(jpgButton);
            jpgButton.addEventListener( MouseEvent.CLICK, onJpegButtonClick );

            var pngButton:TextButton = new TextButton(BUTTON_W, BUTTON_H, "PNG保存");
            pngButton.x = 10;
            pngButton.y = jpgButton.y + jpgButton.height + 10;
            addChild(pngButton);
            pngButton.addEventListener( MouseEvent.CLICK, onPngButtonClick );

            init3D();
        }

        /// JPEG保存ボタンクリック時の処理
        private function onJpegButtonClick(event:MouseEvent):void
        {
            saveGraphicFile(true);
        }

        /// PNG保存ボタンクリック時の処理
        private function onPngButtonClick(event:MouseEvent):void
        {
            saveGraphicFile(false);
        }

        /**
         * 画像ファイルの保存処理
         * @param jpeg trueならJPEGファイル、falseならPNGファイルを保存
         */
        private function saveGraphicFile(jpeg:Boolean):void
        {
            try {
                var bmpData:BitmapData = new BitmapData(SCREEN_W, SCREEN_H, false, 0x000000);
                bmpData.draw(this.stage);

                var fileName:String;
                var byteArray:ByteArray;

                if(jpeg){
                    fileName = "test.jpg";
                    var jpgEncoder:JPGEncoder = new JPGEncoder(80);
                    byteArray = jpgEncoder.encode(bmpData);
                }else{
                    fileName = "test.png";
                    byteArray = PNGEncoder.encode(bmpData);
                }

                var file:File = File.desktopDirectory;
                file = file.resolvePath(fileName);
                var fsw:FileStream = new FileStream();
                fsw.open(file,FileMode.WRITE);
                fsw.writeBytes(byteArray, 0, byteArray.length);
                fsw.close();
            } catch (e:Error) {
                trace(e.toString());
            }
        }

        // _______________________________________________________________________
        //                                                                  Init3D
        private function init3D():void
        {
            //コンテナ生成
            this.container = new Sprite();
            addChild(this.container);
            this.container.x = this.stage.stageWidth  / 2;
            this.container.y = this.stage.stageHeight / 2;

            //シーン生成
            scene = new MovieScene3D( container );

            //カメラ設定
            camera = new Camera3D();
            camera.z = -planeSize;
            camera.focus = 500;
            camera.zoom = 1;

            //マテリアル設定
            var ml:MaterialsList = new MaterialsList(
            {
                all: new ColorMaterial(0xE5A800,1),
                front: new ColorMaterial(0x00E5DA,1),
                back: new ColorMaterial(0x56BFBA,1),
                right: new ColorMaterial(0x3200E5,1),
                left: new ColorMaterial(0x3200E5,1),
                top: new ColorMaterial(0xBF7956,1),
                bottom: new ColorMaterial(0xE5A800,1)
            });

            // オブジェクト生成            
            cubeObj = new Cube( ml, planeSize, planeSize, planeSize, 1, 1, 1 );
            scene.addChild(cubeObj);
            cubeObj.rotationX = 45;
            cubeObj.rotationY = 45;

            var filter:Array = new Array;
            filter.push( new DropShadowFilter() );

            cubeObj.container.filters = filter;
        }

        // _______________________________________________________________________
        //                                                                    Loop
        private function loop3D( event:Event ):void
        {
            //マウス座標でオブジェクトを回転
            valx += this.container.mouseX / 50;
            valy += this.container.mouseY / 50;

            cubeObj.rotationY = valx;
            cubeObj.rotationX = valy;

            //レンダリング
            this.scene.renderCamera( camera );
        }

        // _______________________________________________________________________
        //                                                           onStageResize
        private function onStageResize(event:Event):void
        {
            this.container.x = this.stage.stageWidth  / 2;
            this.container.y = this.stage.stageHeight / 2;
        }

    }
}