function Camera(cameraOpts, opts) {
	this.type = 'camera';
	this.position = cameraOpts.position; this.position.parent = this;
	this.target = cameraOpts.target; this.target.parent = this;
	this.up = cameraOpts.up; this.up.parent = this;
	this.opts = opts || {};
	this.scene = scenes[this.opts.scene];
}
Camera.prototype.load = function() {
	if (this.scene.loaded) {
		return true;
	} else {
		return this.scene.load();
	}
}
Camera.prototype.seek = function(t) {
	if (this.position.seek) this.position.seek(t);
	if (this.target.seek) this.target.seek(t);
	if (this.up.seek) this.up.seek(t);
	this.render();
}
Camera.prototype.tick = function(t) {
	if (this.position.tick) this.position.tick(t);
	if (this.target.tick) this.target.tick(t);
	if (this.up.tick) this.up.tick(t);
	this.render();
}
Camera.prototype.render = function() {
	stage.setCamera(this.position.value(), this.target.value(), this.up.value());
	this.scene.render(stage);
}
Camera.prototype.toScript = function() {
	out = "new Camera({\n";
	out += "\tposition: " + this.position.toScript() + ",\n";
	out += "\ttarget: " + this.target.toScript() + ",\n";
	out += "\tup: " + this.up.toScript() + "\n";
	out += "}, " + JSON.stringify(this.opts) + ")";
	return out;
}

function FadeOut(opts) {
	this.type = 'fadeout';
	this.opts = opts || {};
}
FadeOut.prototype.tick = FadeOut.prototype.seek = function(t) {
	var alpha = t / (this.opts.deathTime - this.opts.birthTime - 500);
	if (alpha < 0.1) return; /* firefox screws up opacities of <0.1 */
	alpha = Math.min(1, alpha);
	stage.ctx.fillStyle = 'rgba(0, 0, 0, ' + alpha + ')';
	stage.enqueueFillRect(-2,0,0, stage.canvas.width, stage.canvas.height);
}
FadeOut.prototype.toScript = function() {
	return "new FadeOut(" + JSON.stringify(this.opts) + ")";
}
function FadeIn(opts) {
	this.type = 'fadein';
	this.opts = opts || {};
}
FadeIn.prototype.tick = FadeIn.prototype.seek = function(t) {
	var alpha = 1 - t / (this.opts.deathTime - this.opts.birthTime);
	if (alpha < 0.1) return; /* firefox screws up opacities of <0.1 */
	alpha = Math.min(1, alpha);
	stage.ctx.fillStyle = 'rgba(0, 0, 0, ' + alpha + ')';
	stage.enqueueFillRect(-2,0,0, stage.canvas.width, stage.canvas.height);
}
FadeIn.prototype.toScript = function() {
	return "new FadeIn(" + JSON.stringify(this.opts) + ")";
}
function Iris(opts) {
	this.type = 'iris';
	this.opts = opts || {};
}
Iris.prototype.tick = Iris.prototype.seek = function(t) {
	var progress = t / (this.opts.deathTime - this.opts.birthTime);
	progress = Math.min(1,progress);
	var width = (1-progress) * stage.canvas.width * 0.7;
	this.enqueueIris(width);
}
Iris.prototype.toScript = function() {
	return "new Iris(" + JSON.stringify(this.opts) + ")";
}
Iris.prototype.enqueueIris = function(width) {
	stage.enqueue(-2, function() {
		this.ctx.fillStyle = 'black';
		this.ctx.beginPath();
		this.ctx.moveTo(0,0);
		this.ctx.lineTo(this.canvas.width,0);
		this.ctx.lineTo(this.canvas.width,this.canvas.height);
		this.ctx.lineTo(0,this.canvas.height);
		this.ctx.closePath();
				
		this.ctx.arc(this.canvas.width / 2, this.canvas.height/2, width,0,Math.PI*2,true);
		this.ctx.fill();
	});
}
