/// <summary>
        /// Function to save the animation data to a stream.
        /// </summary>
        /// <param name="animation">The animation to serialize into the stream.</param>
        /// <param name="stream">The stream that will contain the animation.</param>
        protected override void OnSaveToStream(IGorgonAnimation animation, Stream stream)
        {
            var writer = new GorgonChunkFileWriter(stream, CurrentFileHeader);
            GorgonBinaryWriter binWriter = null;

            try
            {
                writer.Open();
                binWriter = writer.OpenChunk(VersionData);
                binWriter.Write((byte)Version.Major);
                binWriter.Write((byte)Version.Minor);
                writer.CloseChunk();

                binWriter = writer.OpenChunk(AnimationData);
                binWriter.Write(animation.Name);
                binWriter.Write(animation.Length);
                binWriter.Write(animation.IsLooped);
                binWriter.Write(animation.LoopCount);
                writer.CloseChunk();

                // Write out position track.
                if (animation.PositionTrack.KeyFrames.Count > 0)
                {
                    binWriter = writer.OpenChunk(PositionData);
                    binWriter.WriteValue(animation.PositionTrack.InterpolationMode);
                    binWriter.Write(animation.PositionTrack.KeyFrames.Count);

                    for (int i = 0; i < animation.PositionTrack.KeyFrames.Count; ++i)
                    {
                        GorgonKeyVector3 key = animation.PositionTrack.KeyFrames[i];
                        binWriter.Write(key.Time);
                        binWriter.WriteValue(ref key.Value);
                    }

                    writer.CloseChunk();
                }

                // Write out position track.
                if (animation.ScaleTrack.KeyFrames.Count > 0)
                {
                    binWriter = writer.OpenChunk(ScaleData);
                    binWriter.WriteValue(animation.ScaleTrack.InterpolationMode);
                    binWriter.Write(animation.ScaleTrack.KeyFrames.Count);

                    for (int i = 0; i < animation.ScaleTrack.KeyFrames.Count; ++i)
                    {
                        GorgonKeyVector3 key = animation.ScaleTrack.KeyFrames[i];
                        binWriter.Write(key.Time);
                        binWriter.WriteValue(ref key.Value);
                    }

                    writer.CloseChunk();
                }

                // Write out rotation track.
                if (animation.RotationTrack.KeyFrames.Count > 0)
                {
                    binWriter = writer.OpenChunk(RotationData);
                    binWriter.WriteValue(animation.RotationTrack.InterpolationMode);
                    binWriter.Write(animation.RotationTrack.KeyFrames.Count);

                    for (int i = 0; i < animation.RotationTrack.KeyFrames.Count; ++i)
                    {
                        GorgonKeyVector3 key = animation.RotationTrack.KeyFrames[i];
                        binWriter.Write(key.Time);
                        binWriter.WriteValue(ref key.Value);
                    }

                    writer.CloseChunk();
                }

                // Write out size track.
                if (animation.SizeTrack.KeyFrames.Count > 0)
                {
                    binWriter = writer.OpenChunk(SizeData);
                    binWriter.WriteValue(animation.SizeTrack.InterpolationMode);
                    binWriter.Write(animation.SizeTrack.KeyFrames.Count);

                    for (int i = 0; i < animation.SizeTrack.KeyFrames.Count; ++i)
                    {
                        GorgonKeyVector3 key = animation.SizeTrack.KeyFrames[i];
                        binWriter.Write(key.Time);
                        binWriter.WriteValue(ref key.Value);
                    }

                    writer.CloseChunk();
                }

                // Write out bounds track.
                if (animation.RectBoundsTrack.KeyFrames.Count > 0)
                {
                    binWriter = writer.OpenChunk(BoundsData);
                    binWriter.WriteValue(animation.RectBoundsTrack.InterpolationMode);
                    binWriter.Write(animation.RectBoundsTrack.KeyFrames.Count);

                    for (int i = 0; i < animation.RectBoundsTrack.KeyFrames.Count; ++i)
                    {
                        GorgonKeyRectangle key = animation.RectBoundsTrack.KeyFrames[i];
                        binWriter.Write(key.Time);
                        binWriter.WriteValue(ref key.Value);
                    }

                    writer.CloseChunk();
                }

                // Write out colors track.
                if (animation.ColorTrack.KeyFrames.Count > 0)
                {
                    binWriter = writer.OpenChunk(ColorData);
                    binWriter.WriteValue(animation.ColorTrack.InterpolationMode);
                    binWriter.Write(animation.ColorTrack.KeyFrames.Count);

                    for (int i = 0; i < animation.ColorTrack.KeyFrames.Count; ++i)
                    {
                        GorgonKeyGorgonColor key = animation.ColorTrack.KeyFrames[i];
                        binWriter.Write(key.Time);
                        binWriter.WriteValue(ref key.Value);
                    }

                    writer.CloseChunk();
                }

                if (animation.Texture2DTrack.KeyFrames.Count == 0)
                {
                    return;
                }

                binWriter = writer.OpenChunk(TextureData);
                binWriter.Write(animation.Texture2DTrack.KeyFrames.Count);

                for (int i = 0; i < animation.Texture2DTrack.KeyFrames.Count; ++i)
                {
                    GorgonKeyTexture2D key = animation.Texture2DTrack.KeyFrames[i];

                    binWriter.Write(key.Time);

                    if (key.Value == null)
                    {
                        binWriter.WriteValue <byte>(0);
                    }
                    else
                    {
                        binWriter.WriteValue <byte>(1);
                        binWriter.Write(key.Value.Texture.Name);
                        binWriter.Write(key.Value.Texture.Width);
                        binWriter.Write(key.Value.Texture.Height);
                        binWriter.WriteValue(key.Value.Texture.Format);
                        binWriter.Write(key.Value.Texture.ArrayCount);
                        binWriter.Write(key.Value.Texture.MipLevels);
                        binWriter.Write(key.Value.ArrayIndex);
                        binWriter.Write(key.Value.ArrayCount);
                        binWriter.Write(key.Value.MipSlice);
                        binWriter.Write(key.Value.MipCount);
                        binWriter.WriteValue(key.Value.Format);
                    }

                    binWriter.WriteValue(ref key.TextureCoordinates);
                    binWriter.Write(key.TextureArrayIndex);
                }

                writer.CloseChunk();
            }
            finally
            {
                binWriter?.Dispose();
                writer.Close();
            }
        }
        /// <summary>
        /// Function to save the sprite data to a stream.
        /// </summary>
        /// <param name="sprite">The sprite to serialize into the stream.</param>
        /// <param name="stream">The stream that will contain the sprite.</param>
        protected override void OnSaveToStream(GorgonPolySprite sprite, Stream stream)
        {
            var writer = new GorgonChunkFileWriter(stream, CurrentFileHeader);
            GorgonBinaryWriter binWriter = null;

            try
            {
                writer.Open();
                binWriter = writer.OpenChunk(VersionData);
                binWriter.Write((byte)Version.Major);
                binWriter.Write((byte)Version.Minor);
                writer.CloseChunk();

                binWriter = writer.OpenChunk(SpriteData);

                binWriter.WriteValue(sprite.Anchor);

                // If we do not have alpha test information, then skip writing its data.
                binWriter.Write(sprite.AlphaTest != null);
                if (sprite.AlphaTest != null)
                {
                    binWriter.WriteValue(sprite.AlphaTest.Value);
                }

                writer.CloseChunk();

                binWriter = writer.OpenChunk(VertexData);

                binWriter.Write(sprite.Vertices.Count);

                foreach (GorgonPolySpriteVertex vertex in sprite.Vertices)
                {
                    binWriter.WriteValue(vertex.Position);
                    binWriter.WriteValue(vertex.Color);
                    binWriter.WriteValue(vertex.TextureCoordinate);
                }

                writer.CloseChunk();

                // We have no texture data, so don't bother writing out that chunk.
                if (sprite.Texture != null)
                {
                    binWriter = writer.OpenChunk(TextureData);
                    binWriter.Write(sprite.Texture.Texture.Name);
                    binWriter.WriteValue(sprite.TextureOffset);
                    binWriter.WriteValue(sprite.TextureScale);
                    binWriter.WriteValue(sprite.TextureArrayIndex);
                    // Write out as much info about the texture as we can so we can look it up based on these values when loading.
                    binWriter.Write(sprite.Texture.Texture.Width);
                    binWriter.Write(sprite.Texture.Texture.Height);
                    binWriter.WriteValue(sprite.Texture.Texture.Format);
                    binWriter.Write(sprite.Texture.Texture.ArrayCount);
                    binWriter.Write(sprite.Texture.Texture.MipLevels);
                    binWriter.Write(sprite.Texture.ArrayIndex);
                    binWriter.Write(sprite.Texture.ArrayCount);
                    binWriter.Write(sprite.Texture.MipSlice);
                    binWriter.Write(sprite.Texture.MipCount);
                    binWriter.WriteValue(sprite.Texture.Format);
                    binWriter.Close();
                }

                if (sprite.TextureSampler == null)
                {
                    return;
                }

                // Write out information about the texture sampler used by the sprite.
                binWriter = writer.OpenChunk(TextureSamplerData);
                binWriter.WriteValue(sprite.TextureSampler.Filter);
                binWriter.WriteValue(sprite.TextureSampler.BorderColor);
                binWriter.WriteValue(sprite.TextureSampler.ComparisonFunction);
                binWriter.WriteValue(sprite.TextureSampler.WrapU);
                binWriter.WriteValue(sprite.TextureSampler.WrapV);
                binWriter.WriteValue(sprite.TextureSampler.WrapW);
                binWriter.Write(sprite.TextureSampler.MaxAnisotropy);
                binWriter.Write(sprite.TextureSampler.MinimumLevelOfDetail);
                binWriter.Write(sprite.TextureSampler.MaximumLevelOfDetail);
                binWriter.Write(sprite.TextureSampler.MipLevelOfDetailBias);
                writer.CloseChunk();
            }
            finally
            {
                binWriter?.Dispose();
                writer.Close();
            }
        }