Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
534 lines (438 sloc) 14.1 KB
package citrus.view.starlingview {
import citrus.core.starling.StarlingCitrusEngine;
import citrus.math.MathUtils;
import citrus.view.ACitrusCamera;
import starling.display.Sprite;
import flash.display.Sprite;
import flash.geom.Point;
/**
* The Camera for the StarlingView.
*/
public class StarlingCamera extends ACitrusCamera
{
public function StarlingCamera(viewRoot:starling.display.Sprite)
{
super(viewRoot);
}
/**
* @inheritDoc
*/
override protected function initialize():void {
super.initialize();// setup camera lens normally
cameraLensWidth = (_ce as StarlingCitrusEngine).starling.stage.stageWidth;
cameraLensHeight = (_ce as StarlingCitrusEngine).starling.stage.stageHeight;
_aabbData = MathUtils.createAABBData(0, 0, cameraLensWidth / _camProxy.scale, cameraLensHeight / _camProxy.scale, _camProxy.rotation, _aabbData);
_m = (_viewRoot as starling.display.Sprite).transformationMatrix;
}
/**
* @inheritDoc
*/
override protected function onResize(w:Number, h:Number):void
{
cameraLensWidth = (_ce as StarlingCitrusEngine).starling.stage.stageWidth;
cameraLensHeight = (_ce as StarlingCitrusEngine).starling.stage.stageHeight;
}
/**
* multiplies the targeted zoom value by factor.
* @param factor
*/
override public function zoom(factor:Number):void
{
if (_allowZoom)
_zoom *= factor;
else
throw(new Error(this+" is not allowed to zoom. please set allowZoom to true."));
}
/**
* @inheritDoc
*/
override public function zoomFit(width:Number,height:Number,storeInBaseZoom:Boolean = false):Number
{
if (_allowZoom)
{
var ratio:Number;
if (cameraLensHeight / cameraLensWidth > height / width)
ratio = cameraLensWidth / width;
else
ratio = cameraLensHeight / height;
if (storeInBaseZoom)
{
baseZoom = ratio;
_zoom = 1;
return ratio;
}
else
return _zoom = ratio;
}
else
throw(new Error(this+" is not allowed to zoom. please set allowZoom to true."));
}
/**
* rotates the camera by the angle.
* adds angle to targeted rotation value.
* @param angle in radians.
*/
override public function rotate(angle:Number):void
{
if (_allowRotation)
_rotation += angle;
else
throw(new Error(this+" is not allowed to rotate. please set allowRotation to true."));
}
/**
* sets the targeted rotation value to angle.
* @param angle in radians.
*/
override public function setRotation(angle:Number):void
{
if (_allowRotation)
_rotation = angle;
else
throw(new Error(this+" is not allowed to rotate. please set allowRotation to true."));
}
/**
* sets the targeted zoom value to factor.
* @param factor
*/
override public function setZoom(factor:Number):void
{
if (_allowZoom)
_zoom = factor;
else
throw(new Error(this+" is not allowed to zoom. please set allowZoom to true."));
}
/**
* @inheritDoc
*/
override public function getZoom():Number
{
return _zoom;
}
/**
* @inheritDoc
*/
override public function getRotation():Number
{
return _rotation;
}
/**
* Recreates the AABB of the camera.
* will use Math.Utils.createAABBData when allowRotation = true.
*/
public function resetAABBData():void
{
if (!_allowZoom && !_allowRotation)
{
_aabbData.offsetX = _aabbData.offsetY = 0;
_aabbData.rect.setTo(_ghostTarget.x, _ghostTarget.y, cameraLensWidth, cameraLensHeight);
return;
}
if (_allowZoom && !_allowRotation)
{
_aabbData.offsetX = _aabbData.offsetY = 0;
_aabbData.rect.setTo(_ghostTarget.x, _ghostTarget.y, cameraLensWidth / _camProxy.scale, cameraLensHeight / _camProxy.scale);
return;
}
if (_allowRotation && _allowZoom)
{
_aabbData = MathUtils.createAABBData(_ghostTarget.x , _ghostTarget.y, cameraLensWidth / _camProxy.scale, cameraLensHeight / _camProxy.scale, - _camProxy.rotation, _aabbData);
return;
}
if (!_allowZoom && _allowRotation)
{
_aabbData = MathUtils.createAABBData(_ghostTarget.x , _ghostTarget.y, cameraLensWidth, cameraLensHeight, - _camProxy.rotation, _aabbData);
return;
}
}
/**
* @inheritDoc
*/
override public function update():void
{
if(!enabled)
return;
super.update();
offset.setTo(cameraLensWidth * center.x, cameraLensHeight * center.y);
if (_target && followTarget)
{
if (_target.x <= camPos.x - (deadZone.width * .5) / _camProxy.scale || _target.x >= camPos.x + (deadZone.width * .5) / _camProxy.scale )
_targetPos.x = _target.x;
if (_target.y <= camPos.y - (deadZone.height * .5) / _camProxy.scale || _target.y >= camPos.y + (deadZone.height * .5) / _camProxy.scale)
_targetPos.y = _target.y;
_ghostTarget.x += (_targetPos.x - _ghostTarget.x) * easing.x;
_ghostTarget.y += (_targetPos.y - _ghostTarget.y) * easing.y;
}
else if (_manualPosition)
{
_ghostTarget.x = _manualPosition.x;
_ghostTarget.y = _manualPosition.y;
}
if (_allowRotation)
_camProxy.rotation += (_rotation - _camProxy.rotation) * rotationEasing;
resetAABBData();
if (_allowZoom)
{
_camProxy.scale += (mzoom - _camProxy.scale) * zoomEasing;
if (bounds && (boundsMode == BOUNDS_MODE_AABB || boundsMode == BOUNDS_MODE_ADVANCED) )
{
var lwratio:Number = (_aabbData.rect.width*_camProxy.scale ) / bounds.width;
var lhratio:Number = (_aabbData.rect.height*_camProxy.scale ) / bounds.height;
if (_aabbData.rect.width >= bounds.width)
_camProxy.scale = mzoom = lwratio;
else if (_aabbData.rect.height >= bounds.height)
_camProxy.scale = mzoom = lhratio;
}
}
_camProxy.x = ghostTarget.x;
_camProxy.y = ghostTarget.y;
MathUtils.rotatePoint(offset.x/_camProxy.scale, offset.y/_camProxy.scale, _camProxy.rotation, _b.rotoffset);
if ( bounds )
{
if (boundsMode == BOUNDS_MODE_AABB)
{
_b.w2 = (_aabbData.rect.width - _b.rotoffset.x) + _aabbData.offsetX;
_b.h2 = (_aabbData.rect.height - _b.rotoffset.y) + _aabbData.offsetY;
_b.bl = bounds.left + ( MathUtils.abs(_aabbData.offsetX) + _b.rotoffset.x );
_b.bt = bounds.top + ( MathUtils.abs(_aabbData.offsetY) + _b.rotoffset.y );
_b.br = bounds.right - ( (_aabbData.offsetX+_aabbData.rect.width) - _b.rotoffset.x );
_b.bb = bounds.bottom - ( (_aabbData.offsetY+_aabbData.rect.height) - _b.rotoffset.y);
if (_camProxy.x < _b.bl)
_camProxy.x = _b.bl;
if (_camProxy.x > _b.br)
_camProxy.x = _b.br;
if (_camProxy.y < _b.bt)
_camProxy.y = _b.bt;
if (_camProxy.y > _b.bb)
_camProxy.y = _b.bb;
}else if (boundsMode == BOUNDS_MODE_OFFSET)
{
if (_camProxy.x < bounds.left)
_camProxy.x = bounds.left;
if (_camProxy.x > bounds.right)
_camProxy.x = bounds.right;
if (_camProxy.y < bounds.top)
_camProxy.y = bounds.top;
if (_camProxy.y > bounds.bottom)
_camProxy.y = bounds.bottom;
}else if (boundsMode == BOUNDS_MODE_ADVANCED)
{
/**
* Find the furthest camera corner from the offset point, and use the distance from offset to that corner
* as the radius of the circle that will be restricted within the bounds.
*/
if (offset.x <= cameraLensWidth * 0.5) //left
{
if (offset.y <= cameraLensHeight * 0.5) //top
_b.diag2 = MathUtils.DistanceBetweenTwoPoints(offset.x, cameraLensWidth, offset.y, cameraLensHeight);
else
_b.diag2 = MathUtils.DistanceBetweenTwoPoints(offset.x, cameraLensWidth, offset.y, 0);
}else
{
if (offset.y <= cameraLensHeight * 0.5) //top
_b.diag2 = MathUtils.DistanceBetweenTwoPoints(offset.x, 0, offset.y, cameraLensHeight);
else
_b.diag2 = offset.length;
}
_b.diag2 /= _camProxy.scale;
if (_camProxy.x < bounds.left + _b.diag2)
_camProxy.x = bounds.left + _b.diag2;
if (_camProxy.x > bounds.right - _b.diag2)
_camProxy.x = bounds.right - _b.diag2;
if (_camProxy.y < bounds.top + _b.diag2)
_camProxy.y = bounds.top + _b.diag2;
if (_camProxy.y > bounds.bottom - _b.diag2)
_camProxy.y = bounds.bottom - _b.diag2;
}
}
if (parallaxMode == PARALLAX_MODE_TOPLEFT)
{
_m.identity();
_m.rotate(_camProxy.rotation);
_m.scale(1/_camProxy.scale, 1/_camProxy.scale);
_camProxy.offset = _m.transformPoint(offset);
_camProxy.offset.x *= -1;
_camProxy.offset.y *= -1;
}
_aabbData.rect.x = _camProxy.x + _aabbData.offsetX - _b.rotoffset.x;
_aabbData.rect.y = _camProxy.y + _aabbData.offsetY - _b.rotoffset.y;
//reset matrix
_m.identity();
//fake pivot
_m.translate( -_camProxy.x, -_camProxy.y);
//rotation
_m.rotate(_camProxy.rotation);
//zoom
_m.scale(_camProxy.scale, _camProxy.scale);
//offset
_m.translate(offset.x, offset.y);
pointFromLocal(offset.x, offset.y, _camPos);
(_viewRoot as starling.display.Sprite).transformationMatrix = _m;
}
/**
* @param sprite a flash display sprite to render to.
* @deprecated this is now obsolete and doesn't reflect exactly how the camera works as the system changed.
*/
public function renderDebug(sprite:flash.display.Sprite):void
{
var xo:Number, yo:Number, w:Number, h:Number;
//create AABB of camera
var AABB:Object = MathUtils.createAABBData(
_ghostTarget.x ,
_ghostTarget.y ,
cameraLensWidth / _camProxy.scale,
cameraLensHeight / _camProxy.scale,
- _camProxy.rotation);
sprite.graphics.clear();
if (bounds)
{
//draw bounds
sprite.graphics.lineStyle(1, 0xFF0000);
sprite.graphics.drawRect(
bounds.left,
bounds.top,
bounds.width,
bounds.height);
}
//draw targets
sprite.graphics.lineStyle(20, 0xFF0000);
if (_target)
sprite.graphics.drawCircle(_target.x, _target.y, 10);
sprite.graphics.drawCircle(_ghostTarget.x, _ghostTarget.y, 10);
//rotate and scale offset.
var rotScaledOffset:Point = MathUtils.rotatePoint(
offset.x / _camProxy.scale, offset.y / _camProxy.scale,
_camProxy.rotation);
//offset aabb rect according to rotated and scaled camera offset
AABB.rect.x -= rotScaledOffset.x;
AABB.rect.y -= rotScaledOffset.y;
//draw aabb
sprite.graphics.lineStyle(1, 0xFFFF00);
sprite.graphics.drawRect(AABB.rect.x, AABB.rect.y, AABB.rect.width, AABB.rect.height);
var c:Number = Math.cos(_camProxy.rotation);
var s:Number = Math.sin(_camProxy.rotation);
//draw rotated camera rect
xo = AABB.rect.x - AABB.offsetX;
yo = AABB.rect.y - AABB.offsetY;
w = cameraLensWidth / _camProxy.scale;
h = cameraLensHeight / _camProxy.scale;
sprite.graphics.lineStyle(1, 0x00F0FF);
sprite.graphics.beginFill(0x000000, 0.2);
sprite.graphics.moveTo(xo,
yo);
sprite.graphics.lineTo(
xo + (w) * c + (0) * s ,
yo + -(w) * s + (0) * c );
sprite.graphics.lineTo(
xo + (w) * c + (h) * s ,
yo + -(w) * s + (h) * c );
sprite.graphics.lineTo(
xo + (0) * c + (h) * s ,
yo + -(0) * s + (h) * c );
sprite.graphics.lineTo(xo ,
yo);
sprite.graphics.endFill();
if (bounds && !bounds.containsRect(AABB.rect))
{
//aabb is out of bounds, draw where it should be if constrained
var newAABBPos:Point = new Point(AABB.rect.x,AABB.rect.y);
//x
if (AABB.rect.left <= bounds.left)
newAABBPos.x = bounds.left;
else if (AABB.rect.right >= bounds.right)
newAABBPos.x = bounds.right - AABB.rect.width;
//y
if (AABB.rect.top <= bounds.top)
newAABBPos.y = bounds.top;
else if (AABB.rect.bottom >= bounds.bottom)
newAABBPos.y = bounds.bottom - AABB.rect.height;
sprite.graphics.lineStyle(1, 0xFFFFFF , 0.5);
sprite.graphics.drawRect(newAABBPos.x, newAABBPos.y, AABB.rect.width, AABB.rect.height);
//then using the new aabb position... draw the camera.
xo = newAABBPos.x - AABB.offsetX;
yo = newAABBPos.y - AABB.offsetY;
w = cameraLensWidth / _camProxy.scale;
h = cameraLensHeight / _camProxy.scale;
sprite.graphics.lineStyle(1, 0xFFFFFF, 0.5);
sprite.graphics.beginFill(0xFFFFFF, 0.1);
sprite.graphics.moveTo(xo,
yo);
sprite.graphics.lineTo(
xo + (w) * c + (0) * s ,
yo + -(w) * s + (0) * c );
sprite.graphics.lineTo(
xo + (w) * c + (h) * s ,
yo + -(w) * s + (h) * c );
sprite.graphics.lineTo(
xo + (0) * c + (h) * s ,
yo + -(0) * s + (h) * c );
sprite.graphics.lineTo(xo ,
yo);
sprite.graphics.endFill();
//and so the new position of the camera :
var newGTPos:Point = new Point(newAABBPos.x, newAABBPos.y);
sprite.graphics.lineStyle(20, 0xFFFFFF);
sprite.graphics.drawCircle(newGTPos.x, newGTPos.y, 10);
newGTPos.x -= AABB.offsetX;
newGTPos.y -= AABB.offsetY;
sprite.graphics.drawCircle(newGTPos.x, newGTPos.y, 10);
//and we already have the rotated and scaled offset so lets add it.
newGTPos.x += rotScaledOffset.x;
newGTPos.y += rotScaledOffset.y;
sprite.graphics.drawCircle(newGTPos.x, newGTPos.y, 10);
}
}
/**
* equivalent of globalToLocal.
*/
public function pointFromLocal(x:Number,y:Number,resultPoint:Point = null):Point
{
_p.setTo(x, y);
return (_viewRoot as starling.display.Sprite).globalToLocal(_p,resultPoint);
}
/**
* equivalent of localToGlobal
*/
public function pointToLocal(p:Point):Point
{
return (_viewRoot as starling.display.Sprite).localToGlobal(p);
}
/**
* @inheritDoc
*/
override public function get allowZoom():Boolean
{
return _allowZoom;
}
/**
* @inheritDoc
*/
override public function get allowRotation():Boolean
{
return _allowRotation;
}
/**
* @inheritDoc
*/
override public function set allowZoom(value:Boolean):void
{
if (!value)
{
_zoom = 1;
_camProxy.scale = 1;
}
_allowZoom = value;
}
/**
* @inheritDoc
*/
override public function set allowRotation(value:Boolean):void
{
if (!value)
{
_rotation = 0;
_camProxy.rotation = 0;
}
_allowRotation = value;
}
}
}