/*
 *  PAPER    ON   ERVIS  NPAPER ISION  PE  IS ON  PERVI IO  APER  SI  PA
 *  AP  VI  ONPA  RV  IO PA     SI  PA ER  SI NP PE     ON AP  VI ION AP
 *  PERVI  ON  PE VISIO  APER   IONPA  RV  IO PA  RVIS  NP PE  IS ONPAPE
 *  ER     NPAPER IS     PE     ON  PE  ISIO  AP     IO PA ER  SI NP PER
 *  RV     PA  RV SI     ERVISI NP  ER   IO   PE VISIO  AP  VISI  PA  RV3D
 *  ______________________________________________________________________
 *  papervision3d.org / blog.papervision3d.org / osflash.org/papervision3d
 */

// _______________________________________________________________________ Focus

package
{
import flash.display.*;
import flash.events.*;
import flash.ui.Keyboard;
import flash.text.*;

// Import Papervision3D
import org.papervision3d.scenes.*;
import org.papervision3d.objects.*;
import org.papervision3d.cameras.*;
import org.papervision3d.materials.*;
import org.papervision3d.events.*;


public class BouncingCubes extends Sprite
{
	// ___________________________________________________________________ 3D vars

	private var container :Sprite;
	private var scene     :Scene3D;
	private var camera    :Camera3D;

	private var rootNode  :DisplayObject3D;
	// ___________________________________________________________________ Keyboard vars

	private var keyRight   :Boolean = false;
	private var keyLeft    :Boolean = false;
	private var keyForward :Boolean = false;
	private var keyReverse :Boolean = false;

	static public var MAXX:Number = 10;
	static public var MAXY:Number = 10;
	static public var SIZE:Number = 90;
	static public var SIZE2:Number = 100;

	private var out:TextField;
	
	// ___________________________________________________________________________________________ main

	public function BouncingCubes()
	{
		
		stage.quality = "MEDIUM";
		stage.scaleMode = "noScale";

		stage.addEventListener( KeyboardEvent.KEY_DOWN, keyDownHandler );
		stage.addEventListener( KeyboardEvent.KEY_UP, keyUpHandler );

		this.addEventListener( Event.ENTER_FRAME, loop3D );
        stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
        
		init3D();
	}


	// ___________________________________________________________________________________________ init3D

	private function init3D():void
	{
		// Create canvas movieclip and center it
		this.container = new Sprite();
		addChild( this.container );
		this.container.x = 500;
		this.container.y = 300;

		// Create scene
		this.scene = new Scene3D( this.container );

		// Create camera
		camera = new Camera3D();
		camera.x = 3000;
		camera.z = -300;
		camera.y = 3000;
		camera.zoom = 10;
		camera.focus = 100;
		

		// Add an empty object "rootNode" to the scene
		rootNode = scene.addChild( new DisplayObject3D( "rootNode" ) );

		// generate an array of boxes
		for(var x:Number=0; x<MAXX; x++) {
			for(var y:Number=0; y<MAXY; y++) {
				//var color1:WireframeMaterial = new WireframeMaterial(Math.floor(Math.random() * 0xFFFFFF));
				var color2:ColorMaterial = new ColorMaterial(Math.floor(Math.random() * 0xFFFFFF));
				var box0:Box = new Box(color2, SIZE,SIZE,SIZE, {});
				var box:DisplayObject3D = rootNode.addChild(box0, "box"+x+"_"+y);
				box.x = x*SIZE2 - 500;
				box.z = y*SIZE2 - 600;
				box.y = 0;
				box.extra = {vy:0.0, y:Math.floor(Math.random()*200*5) - 300};
			}
		}
			
		
		//var plane :DisplayObject3D = rootNode.addChild( new Plane( new ColorMaterial( 0x333333 ), 1000, 1000, 8, 8 ), "Plane" );
		//camera.lookAt(plane);

		// Position the plane
		//plane.rotationX = -90;
		//plane.y = -25; // We separate the plane from the car to avoid triangle sorting artifacts.
		
		out = new TextField();
		out.text = "Hello World!";
		addChild(out);		

	}


	// ___________________________________________________________________ Keyboard

	private function keyDownHandler( event :KeyboardEvent ):void
	{
		/*switch( event.keyCode )
		{
			case "W".charCodeAt():
			case Keyboard.UP:
				keyForward = true;
				keyReverse = false;
				break;

			case "S".charCodeAt():
			case Keyboard.DOWN:
				keyReverse = true;
				keyForward = false;
				break;

			case "A".charCodeAt():
			case Keyboard.LEFT:
				keyLeft = true;
				keyRight = false;
				break;

			case "D".charCodeAt():
			case Keyboard.RIGHT:
				keyRight = true;
				keyLeft = false;
				break;
		}*/
		//trace("keyDownHandler: " + event.keyCode);
	}


	private function keyUpHandler( event :KeyboardEvent ):void
	{
		/*switch( event.keyCode )
		{
			case "W".charCodeAt():
			case Keyboard.UP:
				keyForward = false;
				break;

			case "S".charCodeAt():
			case Keyboard.DOWN:
				keyReverse = false;
				break;

			case "A".charCodeAt():
			case Keyboard.LEFT:
				keyLeft = false;
				break;

			case "D".charCodeAt():
			case Keyboard.RIGHT:
				keyRight = false;
				break;
		}*/
		//trace("keyUpHandler: " + event.keyCode);
	}

	// ___________________________________________________________________________________________ loop3D

	private function loop3D( event :Event ):void
	{
		// control camera with mouse
		camera.z = -300 + scene.container.mouseX * 5;
		camera.y = Math.max( 0, this.mouseY ) * 5;
		
		var box:DisplayObject3D;
		
		// loop thru all the boxes
		for(var x:Number=0; x<MAXX; x++) {
			for(var y:Number=0; y<MAXY; y++) {
				box = rootNode.getChildByName("box"+x+"_"+y);
				
				box.extra.y += box.extra.vy; // speed -> position
				
				if(box.extra.y <= -300.0) { // bounce
					box.extra.y = -300.0;
					box.extra.vy = (box.extra.vy) * -0.9;
				}
				box.extra.vy-=5.0; // gravity -> speed
				
				box.y = box.extra.y;
				switch((x+y)%3) {
					case 0:
						box.rotationX = (box.y+300)/8;				
						break;
					case 1:
						box.rotationY = (box.y+300)/8;				
						break;
					case 2:
						box.rotationZ = (box.y+300)/8;				
						break;
				}
			}
		}

		// Render the scene
		this.scene.renderCamera( camera );
	}
	
	public function mouseDownHandler(event:MouseEvent):void {
		// on click, randomize their speeds
		for(var x:Number=0; x<MAXX; x++) {
			for(var y:Number=0; y<MAXY; y++) {
				var box:DisplayObject3D = rootNode.getChildByName("box"+x+"_"+y);
				box.extra.vy = Math.random()*250 - 125;
			}
		}
	}
	
	
}
}