This class represents a set of animation loops.
        /// <summary>
        /// Read a file that specifies each of the animation loops.
        /// </summary>
        /// <param name="filename">The file specifying the sprite.</param>
        /// <returns>A sprite, or null if there was a problem reading the file.</returns>
        public static AnimatedSprite SpriteFromFile(string filename, GraphicsDevice gDev)
        {
            XmlReader reader;
            //FileStream inFile;

            //try
            //{
            //inFile = new FileStream(filename, FileMode.Open);
            //}
            //catch (Exception)
            //{
            //    return null;
            //}

            //reader = XmlReader.Create(inFile);
            reader = XmlReader.Create(filename);

            AnimatedSprite ret = null;
            string tempName = null;
            int tempRidx = 0;
            List<AnimationLoop> loopList = null;
            List<SpriteFrame> frames = null;

            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        // Sprite should be the first elment encountered
                        if (reader.Name.Equals("sprite", StringComparison.OrdinalIgnoreCase))
                        {
                            loopList = new List<AnimationLoop>();
                        }
                        // Next is loop
                        if (reader.Name.Equals("loop", StringComparison.OrdinalIgnoreCase))
                        {
                            if (loopList == null)
                            {
                                throw new XmlException("Improperly formatted sprite file : "+filename);
                            }

                            frames = new List<SpriteFrame>();

                            // Attempt to read the name
                            if (reader.MoveToAttribute("name"))
                            {
                                tempName = reader.Value;
                            }
                            else
                            {
                                throw new XmlException("Loop specification needs name attribute.");
                            }

                            // Attempt to read the return index
                            if (reader.MoveToAttribute("retidx"))
                            {
                                tempRidx = int.Parse(reader.Value);
                            }
                            else
                            {
                                throw new XmlException("Loop specification needs retidx attribute.");
                            }
                        }
                        // Last is frame
                        if (reader.Name.Equals("frame", StringComparison.OrdinalIgnoreCase))
                        {

                            if (frames == null)
                            {
                                throw new XmlException("Improperly formatted sprite file : "+filename);
                            }

                            Texture2D tempTex = null;
                            TimeSpan ts;

                            // Attempt to read and load the texture
                            if (reader.MoveToAttribute("texture"))
                            {
                                // Stream the texture
                                tempTex = Helper.LoadTextureStream(Path.GetDirectoryName(filename) + "\\" + reader.Value, gDev);
                            }
                            else
                            {
                                throw new XmlException("Frame specification needs texture attribute.");
                            }

                            // Attempt to read the duration
                            if (reader.MoveToAttribute("duration"))
                            {
                                // Get the time span
                                ts = TimeSpan.FromSeconds(float.Parse(reader.Value));
                            }
                            else
                            {
                                throw new XmlException("Frame specification needs duration attribute.");
                            }

                            // Construct the frame and put it on the list
                            frames.Add(new SpriteFrame(tempTex, ts));
                        }
                        break;

                    case XmlNodeType.EndElement:
                        // When each sprite finishes, construct a sprite based on the loops
                        if (reader.Name.Equals("sprite", StringComparison.OrdinalIgnoreCase))
                        {
                            ret = new AnimatedSprite(loopList.ToArray());
                            loopList.Clear();

                            // Don't need this open anymore
                            reader.Close();
                        }
                        // When each loop finishes, use the frame list to construct a loop and put it on the list
                        if (reader.Name.Equals("loop", StringComparison.OrdinalIgnoreCase))
                        {
                            loopList.Add(new AnimationLoop(tempName, frames.ToArray(), tempRidx));
                            tempName = null;
                            frames = null;
                            tempRidx = 0;
                        }
                        break;
                }
            }

            return ret;
        }
 /// <summary>
 /// Create a new sprite instance with a sprite and a default loop name.
 /// </summary>
 /// <param name="sourceSprite">The sprite to which this is attached.</param>
 /// <param name="defaultLoop">Default animation loop for this instance.</param>
 public AnimatedSpriteInstance(AnimatedSprite sourceSprite, string defaultLoop)
 {
     Sprite = sourceSprite;
     SwitchLoop(defaultLoop);
     sinceLastSwitch = TimeSpan.Zero;
 }