/*

Collada bones example in Away3d

Demonstrates:

How to import an animated collada file that uses bones.
How to posiiton a mouse cursor that hovers over a plane.
how to duplicate animated geometry with the minimum processing overhead.

by Rob Bateman
rob@infiniteturtles.co.uk
http://www.infiniteturtles.co.uk

This code is under the MIT License

Copyright (c)  

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/


package
{
    import away3d.animators.*;
    import away3d.cameras.*;
    import away3d.containers.*;
    import away3d.core.*;
    import away3d.core.base.Mesh;
    import away3d.core.clip.*;
    import away3d.core.utils.*;
    import away3d.events.*;
    import away3d.lights.*;
    import away3d.loaders.*;
    import away3d.loaders.data.*;
    import away3d.materials.*;
    import away3d.primitives.*;
    
    import flash.display.*;
    import flash.events.*;
    import flash.utils.*;
    
    [SWF(backgroundColor="#000000", frameRate="60", quality="LOW", width="800", height="600")]
    
    public class MarioRunMany extends Sprite
    {
        //grass texure for floor
        [Embed(source="assets/floor.jpg")]
        public var Floor:Class;
        
        //shadow texture for under mario
        [Embed(source="assets/shadow.png")]
        public var Shade:Class;
        
        //crosshair texture for mouse pointer
        [Embed(source="assets/position.png")]
        public var Position:Class;
        
        //texture for mario
        [Embed(source="assets/mario_tex.jpg")]
        private var Charmap:Class;
        
        //collada file for mario
        [Embed(source="assets/mario_testrun.dae",mimeType="application/octet-stream")]
        private var Charmesh:Class;
        
        //signature swf
        [Embed(source="assets/signature_peter.swf", symbol="Signature")]
        public var SignatureSwf:Class;
        
        //engine variables
        private var camera:Camera3D;
        private var view:View3D;
        private var scene:Scene3D;
        
        //material variables
        private var material:BitmapMaterial;
        private var shadeMaterial:BitmapMaterial;
        private var positionMaterial:BitmapMaterial;
        private var floorMaterial:TransformBitmapMaterial;
        
        //signature variables
        private var Signature:Sprite;
        private var SignatureBitmap:Bitmap;
        
        //objectvariables
        private var loader:Object3DLoader;
        private var model1:ObjectContainer3D;
        private var mesh:Mesh;
        private var model2:ObjectContainer3D;
        private var model3:ObjectContainer3D;
        private var model4:ObjectContainer3D;
        private var model5:ObjectContainer3D;
        private var position:Plane;
        private var shade1:Plane;
        private var shade2:Plane;
        private var shade3:Plane;
        private var shade4:Plane;
        private var shade5:Plane;
        private var floor:Plane;
        
        //animation varibles
        private var skinAnimation:SkinAnimation;
        
        //navigation variables
        private var rotate:Number;
        private var scrollX:Number;
        private var scrollY:Number;
        
        public function MarioRunMany()
        {
            init();
        }
        
        /**
         * Global initialise function
         */
        private function init():void
        {
            Debug.active = true;
            initEngine();
            initMaterials();
            initObjects();
            initListeners();
        }
        
        /**
         * Initialise the engine
         */
        private function initEngine():void
        {
            scene = new Scene3D();
            camera = new Camera3D({zoom:10, focus:100});
            view = new View3D({camera:camera, scene:scene});
            addChild( view );
            view.addSourceURL("srcview/index.html");
            view.mouseZeroMove = true;
            
            //add signature
            Signature = Sprite(new SignatureSwf());
            SignatureBitmap = new Bitmap(new BitmapData(Signature.width, Signature.height, true, 0));
            stage.quality = StageQuality.HIGH;
            SignatureBitmap.bitmapData.draw(Signature);
            stage.quality = StageQuality.LOW;
            addChild(SignatureBitmap);
        }
        
        /**
         * Initialise the materials
         */
        private function initMaterials():void
        {
            material = new BitmapMaterial(Cast.bitmap(Charmap));
            floorMaterial = new TransformBitmapMaterial(Cast.bitmap(Floor), {repeat:true,scaleX:3,scaleY:3, precision:2});
            shadeMaterial = new BitmapMaterial(Cast.bitmap(Shade));
            positionMaterial = new BitmapMaterial(Cast.bitmap(Position));
        }
        
        /**
         * Initialise the scene objects
         */
        private function initObjects():void
        {
            model1 = Collada.parse(Charmesh, {scaling:0.1, material:material});
            model1.mouseEnabled=false;
            scene.addChild(model1);
            
            mesh = model1.getChildByName("polySurface1") as Mesh;
            
            model2 = new ObjectContainer3D(mesh.clone(), {x:150, mouseEnabled:false});
            scene.addChild(model2);
            
            model3 = new ObjectContainer3D(mesh.clone(), {x:-150, mouseEnabled:false});
            scene.addChild(model3);
            
            model4 = new ObjectContainer3D(mesh.clone(), {z:150, mouseEnabled:false});
            scene.addChild(model4);
            
            model5 = new ObjectContainer3D(mesh.clone(), {z:-150, mouseEnabled:false});
            scene.addChild(model5);
            
            position = new Plane({yUp:true,width:50, height:50, segmentsW:1, segmentsW:1, material:positionMaterial, pushfront:true});
            scene.addChild(position);
            
            shade1 = new Plane({yUp:true, width:100, height:100, segmentsW:1, segmentsW:1, material:shadeMaterial, pushback:true, mouseEnabled:false});
            scene.addChild(shade1);
            
            shade2 = new Plane({yUp:true, width:100, height:100, x:150, segmentsW:1, segmentsW:1, material:shadeMaterial, pushback:true, mouseEnabled:false});
            scene.addChild(shade2);
            
            shade3 = new Plane({yUp:true, width:100, height:100, x:-150, segmentsW:1, segmentsW:1, material:shadeMaterial, pushback:true, mouseEnabled:false});
            scene.addChild(shade3);
            
            shade4 = new Plane({yUp:true,width:100, height:100, z:150, segmentsW:1, segmentsW:1, material:shadeMaterial, pushback:true, mouseEnabled:false});
            scene.addChild(shade4);
            
            shade5 = new Plane({yUp:true, width:100, height:100, z:-150, segmentsW:1, segmentsW:1, material:shadeMaterial, pushback:true, mouseEnabled:false});
            scene.addChild(shade5);
            
            floor = new Plane({yUp:true, width:600, height:600, segmentsW:1, y:0, segmentsH:1, material:floorMaterial, ownCanvas:true, pushback:true})
            scene.addChild(floor);
            
            skinAnimation = model1.animationLibrary.getAnimation("default").animation as SkinAnimation;
        }
        
        /**
         * Initialise the listeners
         */
        private function initListeners():void
        {
            scene.addOnMouseMove(overScene);
            addEventListener( Event.ENTER_FRAME, onEnterFrame );
            onResize(null);
        }
        
        /**
         * Navigation and render loop
         */
        private function onEnterFrame(event:Event):void
        {
            rotate = (Math.floor(Math.atan2(-position.x, -position.z)*(180/Math.PI)) + 180);
            
            scrollY = Math.sin((rotate+90)/180*Math.PI) * (5)
            scrollX = Math.cos((rotate+90)/180*Math.PI) * (5)
            
            floorMaterial.offsetX += scrollX;
            floorMaterial.offsetY += scrollY;
            
            model1.rotationY=rotate;
            model2.rotationY=rotate;
            model3.rotationY=rotate;
            model4.rotationY=rotate;
            model5.rotationY=rotate;
            
            camera.moveTo(0, 70, -10);
            
            camera.rotationX = -mouseY/20;
            
            camera.moveBackward(700 - mouseY/2);
            
            skinAnimation.update(getTimer()*2/1000);
            
            view.render();
        }
        
        /**
         * scene listener for crosshairs plane
         */
        private function overScene(e:MouseEvent3D):void {
            position.x = e.sceneX;
            position.z = e.sceneZ;
        }
        
        /**
         * stage listener for resize events
         */
        private function onResize(event:Event):void
        {
            view.x = stage.stageWidth / 2;
            view.y = stage.stageHeight / 2;
            SignatureBitmap.y = stage.stageHeight - Signature.height;
        }
    }
}