function AnimationTab(parent, closeable, container, index)
{
	TabComponent.call(this, parent, closeable, container, index, Locale.animation, Global.FILE_PATH + "icons/misc/animation.png");

	var self = this;

	this.mixer = null;
	this.object = null;
	this.clock = new Clock();
	
	this.zoom = 120.0; // Pixels/sec
	this.animations = [];

	/**
	 * Menu bar where the options to create animation clip, and play the animation controls are located.
	 *
	 * @attribute bar
	 * @type {Component}
	 */
	this.bar = new Component(this, "div");
	this.bar.size.set(0, 25);
	this.bar.element.style.position = "absolute";
	this.bar.element.style.height = "25px";
	this.bar.element.style.width = "100%";
	this.bar.element.style.backgroundColor = "var(--bar-color)";

	/**
	 * Add animation clip button.
	 *
	 * @attribute add
	 * @type {ButtonText}
	 */
	this.add = new ButtonText(this.bar);
	this.add.position.set(0, 0);
	this.add.size.set(100, this.bar.size.y);
	this.add.setText(Locale.add);
	this.add.updateInterface();
	this.add.setOnClick(function()
	{
		if (self.object !== null)
		{
			if (self.object.animations === undefined)
			{
				self.object.animations = [];
			}

			var clip = new AnimationClip(Locale.animation + self.object.animations.length, 3, []);
			
			// Object 3D
			if (self.object.isObject3D)
			{
				var position = new VectorKeyframeTrack(".position", [0], self.object.position.toArray());
				position.setInterpolation(InterpolateLinear);
				position.setColor("#FF0000");
				clip.tracks.push(position);

				var scale = new VectorKeyframeTrack(".scale", [0], self.object.scale.toArray());
				scale.setInterpolation(InterpolateLinear);
				scale.setColor("#00FF00");
				clip.tracks.push(scale);

				var quaternion = new QuaternionKeyframeTrack(".quaternion", [0], self.object.quaternion.toArray());
				quaternion.setInterpolation(InterpolateLinear);
				quaternion.setColor("#0000FF");
				clip.tracks.push(quaternion);
				
				var visible = new BooleanKeyframeTrack(".visible", [0], [self.object.visible]);
				visible.setInterpolation(InterpolateDiscrete);
				visible.setColor("#FFFF00");
				clip.tracks.push(visible);
			}
			// Material
			else if (self.object.isMaterial)
			{
				if (self.object.color !== undefined)
				{
					var color = new ColorKeyframeTrack(".color", [0], [self.object.color]);
					color.setInterpolation(InterpolateLinear);
					color.setColor("#00FF00");
					clip.tracks.push(color);
				}

				var opacity = new NumberKeyframeTrack(".opacity", [0], [self.object.opacity]);
				opacity.setInterpolation(InterpolateLinear);
				opacity.setColor("#FF0000");
				clip.tracks.push(opacity);
			}

			self.object.animations.push(clip);
			self.attach(self.object);
		}
		else
		{
			Editor.alert(Locale.selectObjectEditAnimation);
		}
	});

	this.play = new ButtonText(this.bar);
	this.play.position.set(100, 0);
	this.play.size.set(100, this.bar.size.y);
	this.play.setText(Locale.play);
	this.play.updateInterface();
	this.play.setOnClick(function()
	{
		if (self.mixer === null)
		{
			Editor.alert("No animation found!");
			return;
		}

		if (self.mixer.playing)
		{
			self.mixer.pause();
			self.play.setText(Locale.play);
		}
		else
		{
			self.mixer.play();
			self.play.setText("Pause");
		}
	});

	this.stop = new ButtonText(this.bar);
	this.stop.position.set(200, 0);
	this.stop.size.set(100, this.bar.size.y);
	this.stop.setText("Stop");
	this.stop.updateInterface();
	this.stop.setOnClick(function()
	{
		if (self.mixer === null)
		{
			Editor.alert("No animation playing!");
			return;
		}

		self.play.setText(Locale.play);
		self.mixer.stop();
	});

	this.zoomSlider = new Slider(this.bar);
	this.zoomSlider.size.set(100, 15);
	this.zoomSlider.position.set(30, 0);
	this.zoomSlider.setStep(10);
	this.zoomSlider.setRange(20, 1000);
	this.zoomSlider.updatePosition(Component.TOP_RIGHT);
	this.zoomSlider.updateSize();
	this.zoomSlider.setValue(this.zoom);
	this.zoomSlider.setOnChange(function()
	{
		self.zoom = self.zoomSlider.getValue();
		self.createTimeline();
	});
	this.zoomSlider.text.style.right = "5px";

	this.zoomText = new Text(this.bar);
	this.zoomText.setText(Locale.zoom);
	this.zoomText.size.set(90, 15);
	this.zoomText.position.set(110, 0);
	this.zoomText.updatePosition(Component.TOP_RIGHT);
	this.zoomText.updateSize();

	/**
	 * Timeline division (movable tab) occupies the hole tab except for the options bar.
	 *
	 * Contains the info on the left and tracks on right side.
	 *
	 * @property timeline
	 * @type {Component}
	 */
	this.timeline = new Component(this, "div");
	this.timeline.element.style.overflowY = "auto";

	/**
	 * Information button tab.
	 *
	 * @property info
	 * @type {Division}
	 */
	this.info = new Division(this.timeline);
	this.info.element.style.backgroundColor = "var(--bar-color)";

	/**
	 * Tracks section.
	 *
	 * @property info
	 * @type {Division}
	 */
	this.tracks = new Division(this.timeline);

	/**
	 * Text shown when there is no object selected to display animation timeline.
	 *
	 * @attribute emptyText
	 * @type {Text}
	 */
	this.emptyText = new Text(this);
	this.emptyText.allowWordBreak(true);
	this.emptyText.setTextSize(12);
	this.emptyText.setTextColor("var(--color-light)");
	this.emptyText.setText(Locale.selectObjectEditAnimation);

	// Temporary variables for mouse movement
	var mouse = 0, initial = 0;

	/**
	 * Resize tab placed between the info and tracks divisions
	 *
	 * @property tab
	 * @type {Component}
	 */
	this.tab = document.createElement("div");
	this.tab.style.backgroundColor = "var(--bar-color)";
	this.tab.style.position = "absolute";
	this.tab.style.cursor = "e-resize";
	this.tab.style.width = "5px";
	this.tab.style.top = "0px";
	this.tab.style.height = "100%";
	this.tab.position = 250;
	this.timeline.element.appendChild(this.tab);

	this.tab.onmousedown = function(event)
	{
		mouse = event.clientX;
		initial = this.position;
		self.tabManager.create();
	};

	/** 
	 * Tab drag event manager.
	 *
	 * @property tabManager
	 * @type {EventManager}
	 */
	this.tabManager = new EventManager();
	this.tabManager.add(window, "mousemove", function(event)
	{
		self.tab.position = initial + (event.clientX - mouse);
		self.updateInterface();
	});
	this.tabManager.add(window, "mouseup", function()
	{
		self.tabManager.destroy();
	});
}
The animation tab is used to display and edit object animations timelines.

Animations can be composed of multiple tracks. A object can have multiple animations.

Each track is composed of keyframes that represent the states of the animation.

@class AnimationTab
@extends {AnimationTab}
@param {Component} parent