function scene_composer ()
{
	this.timeat = 0.0;

	// Scenes are stored in this array
	// The first scene is stored at the end of the array.
	// That way we can traverse the array in reverse order,
	// and pop off scenes that have already been displayed
	// to avoid looping the entire array every frame.
	this.scenes = [];

	this.add = function(scene, func, duration, transitions)
	{
		this.scenes.push(
			{
				scene: scene,
				func: func,
				duration: duration,
				t_start: this.timeat,
				t_end: (this.timeat+duration),
				transitions: transitions
			}
		);
		this.timeat += duration;
	}

	// Reverse the array so that the first scene is at the end.
	this.prepare = function()
	{
		this.scenes.reverse();
		loading_console_write("Demo length: "+this.timeat);

		console.log("Final scene timings:");
		for (i=(this.scenes.length-1); i>=0; i--)
		{
			console.log('scene'+i+': start: '+this.scenes[i].t_start+', end: '+this.scenes[i].t_end);
		}
	}

	// Play the right frame at the right time.
	this.play = function(sec)
	{
		for (i=(this.scenes.length-1); i>=0; i--)
		{
			// Fra og med - til.
			if ( sec >= this.scenes[i].t_start && sec < this.scenes[i].t_end)
			{

				var scene_time = sec-this.scenes[i].t_start;
				var percent = scene_time/this.scenes[i].duration;

				// We need to apply the class for "this." to work inside the function beeing called.
				// function arguments are passed in an array.

				// Reset the final pass shader uniforms.
				//this.scenes[i].scene['final_pass'].uniforms['fadeToBlack'].value = 0;
				final_pass.uniforms['fadeToBlack'].value = 0;

				// Figure out if we should set transition uniforms
				if (this.scenes[i].transitions != undefined)
				{
					var doFade = 0;

					// Inside the in transition time interval
					if (this.scenes[i].transitions.in[1] >= scene_time)
					{
						doFade = 1;
						var val = 1-scene_time/this.scenes[i].transitions.in[1];
					}

					// Inside the out transition interval
					if (this.scenes[i].transitions.out[1] >= this.scenes[i].duration-scene_time)
					{
						doFade = 1;
						var val = 1-(this.scenes[i].duration-scene_time)/this.scenes[i].transitions.out[1];
					}

					// Set appropriate uniforms if transition is active.
					if (doFade == 1)
					{
						if (this.scenes[i].transitions.in[0] == 'black')
						{
							//this.scenes[i].scene['final_pass'].uniforms['fadeToBlack'].value = val;
							final_pass.uniforms['fadeToBlack'].value = val;
						}
					}
				}

				//this.scenes[i].scene['final_pass'].uniforms['fadeToBlack'].value = (Math.sin(sec*4)+1)/2;

				this.scenes[i].func.apply(this.scenes[i].scene, [scene_time, percent]);
				return true;
			} else
			{
				console.log('composer popping off scene '+i);
				this.scenes.pop();
			}
		}
		// Nothing else to display. demo complete.
		//window.location = 'end.html';
		return false;
	}

	this.play_specific = function (i, t)
	{
		this.scenes[i].func.apply(this.scenes[i].scene, [t]);
	}
}