Introduction
In the world of game development with Microsoft XNA, managing and exporting game assets like textures, fonts, models, and animations can be quite a task. To streamline this process, we’ve created a custom XNB exporter that simplifies exporting these assets into a more manageable format. In this post, we will explore the core components of this exporter and how it can be used to handle various types of content.
Key Features of the XNB Exporter
1. Initialization and Setup
public Exporter(string[] files, PictureBox pictureBox, string outPath = "")
{
this.files = files;
this.pictureBox = pictureBox;
this.outPath = outPath;
InitializeContentManager();
}
public void InitializeContentManager()
{
var services = new GameServiceContainer();
var graphicsDeviceService = GraphicsDeviceService.AddRef(IntPtr.Zero, 800, 600);
services.AddService<IGraphicsDeviceService>(graphicsDeviceService);
this.graphicsDevice = graphicsDeviceService.GraphicsDevice;
string contentRootDirectory = Path.Combine(Application.StartupPath, "content");
if (!Directory.Exists(contentRootDirectory))
{
Directory.CreateDirectory(contentRootDirectory);
}
contentManager = new ContentManager(services, contentRootDirectory);
}
The InitializeContentManager
method sets up the ContentManager
and GraphicsDevice
, which are essential for handling XNA content.
2. Loading XNB Files
public List<XnbItem> Load()
{
List<XnbItem> items = new List<XnbItem>();
try
{
foreach (var file in files)
{
try
{
string relativePath = Path.GetRelativePath(ContentRootDirectory, file);
string itemName = Path.ChangeExtension(relativePath, null);
items.Add(new XnbItem { Name = itemName, Path = file });
Debug.LogMessage($"Added item: {itemName}");
}
catch (ArgumentException ex)
{
Debug.LogException($"ArgumentException while processing file '{file}': {ex.Message}");
}
catch (Exception ex)
{
Debug.LogException($"Error processing file '{file}': {ex.Message}");
}
}
OnCompleted?.Invoke();
}
catch (IOException ex)
{
Debug.LogException($"IOException during file loading: {ex.Message}");
}
catch (UnauthorizedAccessException ex)
{
Debug.LogException($"UnauthorizedAccessException during file loading: {ex.Message}");
}
catch (Exception ex)
{
Debug.LogException($"Unexpected error during file loading: {ex.Message}");
}
return items;
}
The Load
method processes the given file paths, adds them to a list of XnbItem
, and handles potential exceptions during the loading process.
3. Displaying Assets
Displaying Textures
public void DisplayImage(Texture2D texture)
{
try
{
texture = ConvertToSupportedFormat(texture);
Microsoft.Xna.Framework.Color[] textureData = new Microsoft.Xna.Framework.Color[texture.Width * texture.Height];
texture.GetData(0, null, textureData, 0, texture.Width * texture.Height);
using (var stream = new MemoryStream())
{
texture.SaveAsPng(stream, texture.Width, texture.Height);
stream.Seek(0, SeekOrigin.Begin);
pictureBox.Image = System.Drawing.Image.FromStream(stream);
}
}
catch (Exception ex)
{
Debug.LogException(ex.Message);
}
}
The DisplayImage
method converts the texture to a supported format and displays it in a PictureBox
.
Displaying Models
public void DisplaySkinnedModel(Model model, string modelName)
{
if (graphicsDevice == null)
{
return;
}
try
{
graphicsDevice.BlendState = BlendState.Opaque;
graphicsDevice.DepthStencilState = DepthStencilState.Default;
foreach (ModelMesh mesh in model.Meshes)
{
foreach (ModelMeshPart part in mesh.MeshParts)
{
SharpDX.Direct3D9.Effect effect = null;
mesh.Draw();
}
}
}
catch (Exception ex)
{
Debug.LogException("Failed to display skinned model '" + modelName + "': " + ex.Message);
}
}
The DisplaySkinnedModel
method is used to render and display a 3D model.
Displaying Fonts
public void DisplayFontAtlas(SpriteFont font, string fileName)
{
using (var stream = new MemoryStream())
{
font.Texture.SaveAsPng(stream, font.Texture.Width, font.Texture.Height);
stream.Seek(0, SeekOrigin.Begin);
pictureBox.Image = System.Drawing.Image.FromStream(stream);
}
}
The ApplyAnimation
method applies animation transforms to the currently loaded model.
5. Converting Texture Formats
public Texture2D ConvertToSupportedFormat(Texture2D texture)
{
if (IsDXTFormat(texture.Format))
{
var data = DecompressDXT(texture);
var convertedTexture = new Texture2D(texture.GraphicsDevice, texture.Width, texture.Height, false, SurfaceFormat.Color);
convertedTexture.SetData(data);
return convertedTexture;
}
return texture;
}
The ConvertToSupportedFormat
method ensures that textures are converted to a supported format if they are in a compressed format like DXT.
Conclusion
The custom XNB exporter provides a robust solution for managing and exporting XNA assets. With functionalities for loading, displaying, and converting various asset types, it streamlines the process of handling game content. Whether you’re working with textures, models, or animations, this exporter can be a valuable tool in your game development toolkit.
Feel free to customize and extend this exporter to better fit your needs. Happy exporting!