package
{
    import flash.desktop.*;
    import flash.display.*;
    import flash.events.*;
    import flash.filesystem.*;
    import flash.geom.*;
    import flash.net.*;
    import flash.text.*;

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

    [SWF(width="240", height="240", backgroundColor="#000000")]

    public class DragDrop3D extends Sprite
    {
        private var container : Sprite;
        private var scene     : Scene3D;
        private var camera    : Camera3D;

        private var planeObj  : DisplayObject3D;
        private var planeSize : int = 300;      //Planeオブジェクト1辺の長さ
        private var segment   : int = 1;        //面の分割数

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

        private var textField:TextField;    ///< テキストフィールド
        private var loader:Loader;          ///< ローダー

        static public const
            TEXTURE_W:int = 240,        ///< テクスチャの幅
            TEXTURE_H:int = 240,        ///< テクスチャの高さ
            WND_WIDTH:uint = 240,       ///< ウインドウの幅
            WND_HEIGHT:uint = 240;      ///< ウインドウの高さ

        /// コンストラクタ
        public function DragDrop3D():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);

            init3D();

            //テキストフィールドの生成
            textField=new TextField();
            textField.text="画像ファイル(GIF,PNG,JPG)をこのウインドウにドラッグして下さい。";
            textField.autoSize=TextFieldAutoSize.LEFT;
            textField.wordWrap = true;
            textField.width = WND_WIDTH;
            textField.height = WND_HEIGHT;
            textField.textColor = 0xFFFFFF;
            addChild(textField);

            //イベントの追加
            addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER,onDragEnter);
            addEventListener(NativeDragEvent.NATIVE_DRAG_DROP,onDragDrop);
        }

        /// ドラッグインイベントの処理
        public function onDragEnter(evt:NativeDragEvent):void {
            //クリップボードの取得
            var cb:Clipboard=evt.clipboard;

            //ドラッグ可能かどうかのチェック
            if ( cb.hasFormat(ClipboardFormats.URL_FORMAT) ) {
                //ドロップの許可
                NativeDragManager.acceptDragDrop(this);
            }
        }

        /// ファイルパスから拡張子が合致するか調べる
        public function cmpFileExtension(filePath:String, fileExt:String):Boolean {
            // 本当は正規表現できっちりやったほうがよいと思うが、^がなんかうまく動かないので、とりあえず            
            var reg:RegExp = new RegExp(fileExt, "i");
            var ret:int = filePath.search(reg);

            if(ret == -1){
                return false;
            }

            if( (filePath.length-fileExt.length) == ret ){
                return true;
            }
            return false;
        }

        ///ドロップイベントの処理
        public function onDragDrop(evt:NativeDragEvent):void {
            var result:String="DragDrop3D\n\n";
            //クリップボードの取得
            var cb:Clipboard=evt.clipboard;

            if (cb.hasFormat(ClipboardFormats.URL_FORMAT)) {
                var url:String=String(cb.getData(ClipboardFormats.URL_FORMAT));
                result+="URL:"+url+"\n\n";

                if( cmpFileExtension(url, ".gif") ||
                    cmpFileExtension(url, ".png") ||
                    cmpFileExtension(url, ".jpg") ||
                    cmpFileExtension(url, ".jpeg")
                    ){

                    //  画像ファイルの場合
                    if( loader == null ){
                        loader = new Loader();
                    }
                    loader.load(new URLRequest(url));
                }

            }

            textField.text=result;
        }

        /// 3D関係の初期化
        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 Scene3D( container );

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

            //BitmapDataの作成。Bitmapに角丸矩形を描く
            var bmpData:BitmapData = new BitmapData(TEXTURE_W,TEXTURE_H,true,0x00000000);
            drawTextureBG(bmpData);

            //マテリアル設定
            var material:BitmapMaterial = new BitmapMaterial(bmpData);
            material.oneSide = false;

            //Planeオブジェクト生成
            planeObj = scene.addChild( new Plane( material, planeSize, planeSize, segment, segment) );
        }

        /// テクスチャのベースとなる角丸矩形を描画      
        private function drawTextureBG(bmp:BitmapData):void
        {
            var rrect:Shape = new Shape();
            rrect.graphics.lineStyle(0,0x00000000);
            rrect.graphics.beginFill(0x47FF8A);
            rrect.graphics.drawRoundRect(0,0,TEXTURE_W,TEXTURE_H,50);
            rrect.graphics.endFill();
            bmp.draw(rrect);
        }

        // _______________________________________________________________________
        //                                                                    Loop
        private function loop3D( event:Event ):void
        {
            valx += 1;
            valy += 1;
            planeObj.rotationY = valx;
            planeObj.rotationX = valy;

            //テクスチャ描画
            drawTextureBG(planeObj.material.bitmap);
            if(loader != null){
                var graphic_w:int = TEXTURE_W - 20;
                var graphic_h:int = TEXTURE_H - 20;
                var mat:Matrix = new Matrix();

                mat.scale(graphic_w/loader.width, graphic_h/loader.height);
                mat.translate( (TEXTURE_W - graphic_w)/2, (TEXTURE_H - graphic_h)/2 );
                planeObj.material.bitmap.draw(loader, mat);
            }
            planeObj.material.updateBitmap();

            //レンダリング
            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;
        }

    }
}