Running on Empty

The few things I know, I like to share.

XNA Framework GameEngine Development. (Part 5, TextureManager:GameComponent)

Introduction

Welcome to Part 5 of the XNA Framework GameEngine Development series.  In this article, I will implement the texture interface and the TextureManager.

IRoeTexture interface.  Updated, Use LoadContent, UnloadContent instead of Initialize.

The IRoeTexture interface will be used to identify any texture in the engine.  It will also be used in the same way IRoeShader is used to allow users to extend the base engine with their own texture types.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Graphics;

namespace RoeEngine2.Interfaces
{
    public interface IRoeTexture
    {
        string FileName
        {
            get;
            set;
        }

        Texture BaseTexture
        {
            get;
        }

        bool ReadyToRender
        {
            get;
        }

        void LoadContent();

        void UnloadContent();
    }
}

RoeTexture class.  Updated, Use LoadContent, UnloadContent instead of Initialize.

This class will be used to store and initialize all textures in the engine.  Essentially, it will contain the FileName of the texture we want to load from the content pipeline, the ReadyToRender property will tell the engine if the texture is loaded and the Initialize method which will use the content manager to load the texture.  Finally, the RoeTexture class will make use of the BaseTexture property to reference the newly loaded texture.

using System;
using System.Collections.Generic;
using System.Text;
using RoeEngine2.Interfaces;
using Microsoft.Xna.Framework.Graphics;
using RoeEngine2.Managers;

namespace RoeEngine2.Texures
{
    public class RoeTexture : IRoeTexture
    {
        private string _fileName;
        /// <summary>
        /// The file name of the asset.
        /// </summary>
        public string FileName
        {
            get { return _fileName; }
            set { _fileName = value; }
        }

        private Texture _baseTexture;
        ///<summary>
        ///Gets the underlying Effect.
        ///</summary>
        public Texture BaseTexture
        {
            get { return _baseTexture; }
        }

        private bool _readyToRender = false;
        ///<summary>
        ///Is the texture ready to be rendered.
        ///</summary>
        public bool ReadyToRender
        {
            get { return _readyToRender; }
        }

        /// <summary>
        /// Construct a new RoeTexture.
        /// </summary>
        public RoeTexture()
        {

        }

        /// <summary>
        /// Construct a new RoeTexture.
        /// </summary>
        /// <param name="fileName">The asset file name.</param>
        public RoeTexture(string fileName)
        {
            _fileName = fileName;
        }

        public void LoadContent()
        {
            if (!String.IsNullOrEmpty(_fileName))
            {
                _baseTexture = EngineManager.ContentManager.Load<Texture>(_fileName);
                _readyToRender = true;
            }
        }

        public void UnloadContent()
        {
            _baseTexture.Dispose();
        }
    }
}

TextureManager class.  Added RemoveTexture.

This class is the main container for everything that has to do with Textures.  You may recognize the implementation from the ShaderManager, it is purposefully done.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections;
using RoeEngine2.Interfaces;
using RoeEngine2.Texures;

namespace RoeEngine2.Managers
{
    public class TextureManager : GameComponent
    {
        private static Dictionary<string, IRoeTexture> _textures = new Dictionary<string, IRoeTexture>();

        private static bool _initialized = false;
        /// <summary>
        /// Is the TextureManagers Initialized, used for test cases and setup of Effects.
        /// </summary>
        public static bool Initialized
        {
            get { return _initialized; }
        }

        private static int _texturesLoaded = 0;
        /// <summary>
        /// The number of textures that are currently loaded.
        /// Use this for user loading bar feedback.
        /// </summary>
        public static int TexturesLoaded
        {
            get { return _texturesLoaded; }
        }

        /// <summary>
        /// Create the shader Managers.
        /// </summary>
        /// <param name="game"></param>
        public TextureManager(Game game)
            : base(game)
        {
        }

        /// <summary>
        /// Add a shader of type RoeTexture.
        /// </summary>
        /// <param name="newTexture"></param>
        /// <param name="textureName"></param>
        public static void AddTexture(IRoeTexture newTexture, string textureName)
        {
            if (textureName != null && !_textures.ContainsKey(textureName))
            {
                _textures.Add(textureName, newTexture);
                if (_initialized)
                {
                    newTexture.LoadContent();
                }
            }
        }

        public static void RemoveTexture(string textureName)
        {
            if (textureName != null && _textures.ContainsKey(textureName))
            {               
                if (_initialized)
                {
                    _textures[textureName].UnloadContent();
                    _textures.Remove(textureName);
                    _texturesLoaded--;
                }               
            }
        }

        /// <summary>
        /// Get a texture
        /// </summary>
        /// <param name="textureId"></param>
        /// <returns></returns>
        public static IRoeTexture GetTexture(string textureName)
        {
            if (textureName != null && _textures.ContainsKey(textureName))
            {
                return _textures[textureName];
            }
            return null;
        }

        /// <summary>
        /// Create the shaders.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

            foreach (IRoeTexture texture in _textures.Values)
            {
                if (!texture.ReadyToRender)
                {
                    texture.LoadContent();
                }
            }

            _initialized = true;
        }
    }
}

Using the TextureManager GameComponent

Add the following code to the Properties section of RoeEngine2.

private static TextureManager _textureManagers = null;

And in the RoeEngine2 Constructor

// Init texture Managers
_textureManagers = new TextureManager(this);
Components.Add(_textureManagers);

//TODO include other inits here!

Optional TDD

Add the following test cases to the RoeEngineTestCases class

[Test, Category("TextureManager")]
public void TextureManagerCreated()
{
    Assert.IsTrue(TextureManager.Initialized);
}

[Test, Category("TextureManager")]
public void TextureManagerAddGetFailed()
{
    Assert.IsNull(TextureManager.GetTexture("testtexture"));
}

Conclusion

In this article I introduce the IRoeTexture, the RoeTexture class and the TextureManager.  I will be revisiting these classes from time to time.

Your feedback is very important, I very much enjoy reading your comments and suggestions.

Advertisements

January 16, 2008 - Posted by | C#, GameComponent, TDD, XBOX360, XNA

7 Comments »

  1. I made an update to use the LoadContent, UnloadContent as well as RemoveTexture method.

    Comment by roecode | January 17, 2008 | Reply

  2. I think a check on ( _baseTexture != null ) in RoeTexture.UnloadContent() function must be done before disposing it, isn’t that right ?

    Comment by Karim Kenawy | March 25, 2008 | Reply

  3. This code was depreciated in newer versions. In fact, article 20 is going to introduce a completely new base engine and support managers.

    Comment by roecode | March 25, 2008 | Reply

  4. Thanks for this amazing XNA Engine series! I’ve seen that textureLoaded doesn’t raise in the AddTexture method.

    Comment by ET | April 11, 2008 | Reply

  5. Minor typo:
    namespace RoeEngine2.Texures
    Should be
    namespace RoeEngine2.Textures

    I suppose?

    Comment by Iltar van der Berg | October 19, 2009 | Reply

  6. I think there must be _texturesLoaded++ in AddTexture method.

    Comment by Stealth2009 | November 4, 2009 | Reply

  7. […] thing I discovered over that spring break was the concept of a texture manager – I wish I’d known about this earlier; it would have made things significantly […]

    Pingback by Malcolm Crum | April 17, 2011 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: