package org.papervision3d.cameras { import flash.display.Sprite; import flash.display.Stage; import flash.events.Event; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.geom.Point; import flash.text.TextField; import flash.text.TextFormat; import flash.ui.Keyboard; import org.papervision3d.view.Viewport3D; /** *
* DebugCamera3D serves as a tool to allow you control * the camera with your mouse and keyboard while displaying information * about the camera when testing your swf. Due to its nature, * the Keyboard and Mouse Events may interfere with your custom Keyboard and Mouse Events. * This camera is in no way intended for production use. *
* ** Click and drag for mouse movement. The keys * are setup as follows: *
*
* w = forward
* s = backward
* a = left
* d = right
* q = rotationZ--
* e = rotationZ++
* r = fov++
* f = fov--
* t = near++
* g = near--
* y = far++
* h = far--
*
*
* @author John Lindquist
*/
public class DebugCamera3D extends Camera3D
{
/** @private */
protected var _propertiesDisplay:Sprite;
/** @private */
protected var _inertia:Number = 3;
/** @private */
protected var viewportStage:Stage;
/** @private */
protected var startPoint:Point;
/** @private */
protected var startRotationY:Number;
/** @private */
protected var startRotationX:Number;
/** @private */
protected var targetRotationY:Number = 0;
/** @private */
protected var targetRotationX:Number = 0;
/** @private */
protected var keyRight:Boolean = false;
/** @private */
protected var keyLeft:Boolean = false;
/** @private */
protected var keyForward:Boolean = false;
/** @private */
protected var keyBackward:Boolean = false;
/** @private */
protected var forwardFactor:Number = 0;
/** @private */
protected var sideFactor:Number = 0;
/** @private */
protected var xText:TextField;
/** @private */
protected var yText:TextField;
/** @private */
protected var zText:TextField;
/** @private */
protected var rotationXText:TextField;
/** @private */
protected var rotationYText:TextField;
/** @private */
protected var rotationZText:TextField;
/** @private */
protected var fovText:TextField;
/** @private */
protected var nearText:TextField;
/** @private */
protected var farText:TextField;
/** @private */
protected var viewport3D:Viewport3D;
/**
* DebugCamera3D
*
* @param viewport Viewport to render to. @see org.papervision3d.view.Viewport3D
* @param fovY Field of view (vertical) in degrees.
* @param near Distance to near plane.
* @param far Distance to far plane.
*/
public function DebugCamera3D(viewport3D:Viewport3D, fovY:Number = 90, near:Number = 10, far:Number = 5000)
{
super(fovY, near, far, true);
this.viewport3D = viewport3D;
this.viewport = viewport3D.sizeRectangle;
this.focus = (this.viewport.height / 2) / Math.tan((fovY/2) * (Math.PI/180));
this.zoom = this.focus / near;
this.focus = near;
this.far = far;
displayProperties();
checkStageReady();
}
/**
* Checks if the viewport is ready for events
*/
private function checkStageReady():void
{
if(viewport3D.containerSprite.stage == null)
{
viewport3D.containerSprite.addEventListener(Event.ADDED_TO_STAGE, onAddedToStageHandler);
}
else
{
setupEvents();
}
}
/**
* Dispatched with the viewport container is added to the stage
*/
protected function onAddedToStageHandler(event:Event):void
{
setupEvents();
}
/**
* Builds the Sprite that displays the camera properties
*/
protected function displayProperties():void
{
_propertiesDisplay = new Sprite();
_propertiesDisplay.graphics.beginFill(0x000000);
_propertiesDisplay.graphics.drawRect(0, 0, 100, 100);
_propertiesDisplay.graphics.endFill();
_propertiesDisplay.x = 0;
_propertiesDisplay.y = 0;
var format:TextFormat = new TextFormat("_sans", 9);
xText = new TextField();
yText = new TextField();
zText = new TextField();
rotationXText = new TextField();
rotationYText = new TextField();
rotationZText = new TextField();
fovText = new TextField();
nearText = new TextField();
farText = new TextField();
var textFields:Array = [xText, yText, zText, rotationXText, rotationYText, rotationZText, fovText, nearText, farText];
var textFieldYSpacing:int = 10;
for (var i:Number = 0;i < textFields.length; i++)
{
textFields[i].width = 100;
textFields[i].selectable = false;
textFields[i].textColor = 0xFFFF00;
textFields[i].text = '';
textFields[i].defaultTextFormat = format;
textFields[i].y = textFieldYSpacing * i;
_propertiesDisplay.addChild(textFields[i]);
}
viewport3D.addChild(_propertiesDisplay);
}
/**
* Sets up the Mouse and Keyboard Events required for adjusting the camera properties
*/
protected function setupEvents():void
{
viewportStage = viewport3D.containerSprite.stage;
viewportStage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
viewportStage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
viewportStage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
viewportStage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
viewportStage.addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
/**
* The default handler for the MouseEvent.MOUSE_DOWN
event.
*
* @param The event object.
*/
protected function mouseDownHandler(event:MouseEvent):void
{
viewportStage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
startPoint = new Point(viewportStage.mouseX, viewportStage.mouseY);
startRotationY = this.rotationY;
startRotationX = this.rotationX;
}
/**
* The default handler for the MouseEvent.MOUSE_MOVE
event.
*
* @param The event object.
*/
protected function mouseMoveHandler(event:MouseEvent):void
{
targetRotationY = startRotationY - (startPoint.x - viewportStage.mouseX) / 2;
targetRotationX = startRotationX + (startPoint.y - viewportStage.mouseY) / 2;
}
/**
* Removes the mouseMoveHandler on the MouseEvent.MOUSE_UP
event.
*
* @param The event object.
*/
protected function mouseUpHandler(event:MouseEvent):void
{
viewportStage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}
/**
* Adjusts the camera based on the keyCode from the KeyboardEvent.KEY_DOWN
event.
*
* @param The event object.
*/
protected function keyDownHandler(event:KeyboardEvent):void
{
switch( event.keyCode )
{
case "W".charCodeAt():
case Keyboard.UP:
keyForward = true;
keyBackward = false;
break;
case "S".charCodeAt():
case Keyboard.DOWN:
keyBackward = 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;
case "Q".charCodeAt():
rotationZ--;
break;
case "E".charCodeAt():
rotationZ++;
break;
case "F".charCodeAt():
fov--;
break;
case "R".charCodeAt():
fov++;
break;
case "G".charCodeAt():
near -= 10;
break;
case "T".charCodeAt():
near += 10;
break;
case "H".charCodeAt():
far -= 10;
break;
case "Y".charCodeAt():
far += 10;
break;
}
}
/**
* Checks which Key is released on the KeyboardEvent.KEY_UP
event
* and toggles that key's movement off.
*
* @param The event object.
*/
protected function keyUpHandler(event:KeyboardEvent):void
{
switch( event.keyCode )
{
case "W".charCodeAt():
case Keyboard.UP:
keyForward = false;
break;
case "S".charCodeAt():
case Keyboard.DOWN:
keyBackward = false;
break;
case "A".charCodeAt():
case Keyboard.LEFT:
keyLeft = false;
break;
case "D".charCodeAt():
case Keyboard.RIGHT:
keyRight = false;
break;
}
}
/**
* Checks which keys are down and adjusts the camera accorindingly on the Event.ENTER_FRAME
event.
* Also updates the display of properties.
*
* @param The event object.
*/
protected function onEnterFrameHandler(event:Event):void
{
if(keyForward)
{
forwardFactor += 50;
}
if(keyBackward)
{
forwardFactor += -50;
}
if(keyLeft)
{
sideFactor += -50;
}
if(keyRight)
{
sideFactor += 50;
}
// rotation
var rotationX:Number = this.rotationX + ( targetRotationX - this.rotationX ) / _inertia;
var rotationY:Number = this.rotationY + ( targetRotationY - this.rotationY ) / _inertia;
this.rotationX = Math.round(rotationX * 10) / 10;
this.rotationY = Math.round(rotationY * 10) / 10;
// position
forwardFactor += ( 0 - forwardFactor ) / _inertia;
sideFactor += ( 0 - sideFactor ) / _inertia;
if (forwardFactor > 0)
{
this.moveForward(forwardFactor);
}else
{
this.moveBackward(-forwardFactor);
}
if (sideFactor > 0)
{
this.moveRight(sideFactor);
}else
{
this.moveLeft(-sideFactor);
}
xText.text = 'x:' + int(x);
yText.text = 'y:' + int(y);
zText.text = 'z:' + int(z);
rotationXText.text = 'rotationX:' + int(rotationX);
rotationYText.text = 'rotationY:' + int(rotationY);
rotationZText.text = 'rotationZ:' + int(rotationZ);
fovText.text = 'fov:' + Math.round(fov);
nearText.text = 'near:' + Math.round(near);
farText.text = 'far:' + Math.round(far);
}
/**
* A Sprite that displays the current properties of your camera
*/
public function get propsDisplay():Sprite
{
return _propertiesDisplay;
}
public function set propsDisplay(propsDisplay:Sprite):void
{
_propertiesDisplay = propsDisplay;
}
/**
* The amount of resistance to the change in velocity when updating the camera rotation with the mouse
*/
public function get inertia():Number
{
return _inertia;
}
public function set inertia(inertia:Number):void
{
_inertia = inertia;
}
}
}