// Project: XnaGraphicEngine, File: Texture.cs
// Namespace: XnaGraphicEngine.Graphics, Class: Texture
// Path: C:\code\XnaGraphicEngine\Graphics, Author: Abi
// Code lines: 614, Size of file: 17,23 KB
// Creation date: 07.09.2006 05:56
// Last modified: 27.10.2006 02:42
// Generated with Commenter by abi.exDream.com
#region Using directives
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.IO;
using XnaGraphicEngine;
using XnaGraphicEngine.Game;
using XnaGraphicEngine.Helpers;
#endregion
namespace XnaGraphicEngine.Graphics
{
///
/// Texture class helping you with using DirectX Textures and handling
/// possible errors that can happen while loading (stupid DirectX
/// error messages telling you absolutly nothing, so a lot of pre-checks
/// help you determinate the error before even calling DirectX methods).
///
public class Texture : IGraphicContent
{
#region Variables
///
/// If you want to add a default extension if none is given, set it here.
/// If this is empty, no default extension will be applied.
///
protected const string AddExtensionIfNoneGiven = "dds";
///
/// Texture filename
///
protected string texFilename = "";
///
/// Get filename of texture.
///
public string Filename
{
get
{
return texFilename;
} // get
} // Filename
///
/// Size of texture
///
protected int texWidth, texHeight;
///
/// Width of texture
///
public int Width
{
get
{
return texWidth;
} // get
} // Width
///
/// Height of texture
///
public int Height
{
get
{
return texHeight;
} // get
} // Height
///
/// Gfx rectangle
///
/// Rectangle
public Rectangle GfxRectangle
{
get
{
return new Rectangle(0, 0, texWidth, texHeight);
} // get
} // GfxRectangle
///
/// Size of half a pixel, will be calculated when size is set.
///
private Vector2 precaledHalfPixelSize = Vector2.Zero;//.Empty;
///
/// Get the size of half a pixel, used to correct texture
/// coordinates when rendering on screen, see Texture.RenderOnScreen.
///
public Vector2 HalfPixelSize
{
get
{
return precaledHalfPixelSize;
} // get
} // HalfPixelSize
///
/// Calc half pixel size
///
protected void CalcHalfPixelSize()
{
precaledHalfPixelSize = new Vector2(
(1.0f / (float)texWidth) / 2.0f,
(1.0f / (float)texHeight) / 2.0f);
} // CalcHalfPixelSize()
///
/// Graphic Texture
///
protected Microsoft.Xna.Framework.Graphics.Texture2D internalXnaTexture;
///
/// Xna texture
///
public virtual Microsoft.Xna.Framework.Graphics.Texture2D XnaTexture
{
get
{
return internalXnaTexture;
} // get
} // XnaTexture
///
/// Loading succeeded?
///
protected bool loaded = true;
///
/// Error?
///
protected string error = "";
///
/// Is texture valid? Will be false if loading failed.
///
public virtual bool Valid
{
get
{
return loaded &&
internalXnaTexture != null;
} // get
} // Valid
///
/// Has alpha?
///
protected bool hasAlpha = false;
///
/// Has texture alpha information?
///
public bool HasAlphaPixels
{
get
{
return hasAlpha;
} // get
} // HasAlphaPixels
#endregion
#region Constructor
///
/// Create texture from given filename.
///
/// Set filename, must be relative and be a
/// valid file in the textures directory.
public Texture(string setFilename)
{
if (String.IsNullOrEmpty(setFilename))
throw new ArgumentNullException("setFilename",
"Unable to create texture without valid filename.");
// Set content name (cut off extension!)
texFilename = StringHelper.ExtractFilename(setFilename, true);
Load();
BaseGame.RegisterGraphicContentObject(this);
} // Texture(setFilename)
///
/// Create texture, protected version for derived classes.
///
protected Texture()
{
} // Texture()
///
/// Create texture by just assigning a Texture2D.
///
/// Tex
public Texture(Texture2D tex)
{
internalXnaTexture = tex;
// Get info from the texture directly.
texWidth = internalXnaTexture.Width;
texHeight = internalXnaTexture.Height;
// We will use alpha for Dxt3, Dxt5 or any format starting with "A",
// there are a lot of those (A8R8G8B8, A4R4G4B4, A8B8G8R8, etc.)
hasAlpha =
internalXnaTexture.Format == SurfaceFormat.Dxt5 ||
internalXnaTexture.Format == SurfaceFormat.Dxt3 ||
internalXnaTexture.Format.ToString().StartsWith("A");
loaded = true;
CalcHalfPixelSize();
} // Texture(tex)
#endregion
#region Disposing
///
/// Dispose
///
public virtual void Dispose()
{
if (internalXnaTexture != null)
internalXnaTexture.Dispose();
internalXnaTexture = null;
loaded = false;
} // Dispose()
#endregion
#region Load
///
/// Load or reload texture.
///
public void Load()
{
string fullFilename =
Path.Combine(Directories.ContentDirectory, texFilename);
// Try to load texture
try
{
// Try loading as 2d texture
internalXnaTexture = BaseGame.Content.Load(fullFilename);
// Get info from the texture directly.
texWidth = internalXnaTexture.Width;
texHeight = internalXnaTexture.Height;
// We will use alpha for Dxt3, Dxt5 or any format starting with "A",
// there are a lot of those (A8R8G8B8, A4R4G4B4, A8B8G8R8, etc.)
hasAlpha =
internalXnaTexture.Format == SurfaceFormat.Dxt5 ||
internalXnaTexture.Format == SurfaceFormat.Dxt3 ||
internalXnaTexture.Format.ToString().StartsWith("A");
loaded = true;
CalcHalfPixelSize();
} // try
catch (Exception ex)
{
#if XBOX360
// Failed to load
loaded = false;
// Create dummy empty texture (to prevent any errors in the game)
internalXnaTexture = new Texture2D(BaseGame.Device,
16, 16, 0, ResourceUsage.None,
SurfaceFormat.Dxt1,
ResourceManagementMode.Automatic);
Log.Write("Failed to load texture " + fullFilename +
", will use empty texture! Error: " + ex.ToString());
#else
// Try again with filename
// Add default extension if none is given
if (AddExtensionIfNoneGiven.Length > 0 &&
StringHelper.GetExtension(texFilename).Length == 0)
texFilename = texFilename + "." + AddExtensionIfNoneGiven;
// Build full filename
fullFilename =
Directories.ContentDirectory + "\\" + texFilename;
// Check if file exists, else we can't continue loading!
if (File.Exists(fullFilename))
{
// Finally load texture
internalXnaTexture = Texture2D.FromFile(
BaseGame.Device, fullFilename);
// Get info from the texture directly.
texWidth = internalXnaTexture.Width;
texHeight = internalXnaTexture.Height;
// We will use alpha for Dxt3, Dxt5 or any format starting with "A",
// there are a lot of those (A8R8G8B8, A4R4G4B4, A8B8G8R8, etc.)
hasAlpha =
internalXnaTexture.Format == SurfaceFormat.Dxt5 ||
internalXnaTexture.Format == SurfaceFormat.Dxt3 ||
internalXnaTexture.Format.ToString().StartsWith("A");
loaded = true;
CalcHalfPixelSize();
} // if (File.Exists)
else
{
// Failed to load
loaded = false;
// Create dummy empty texture (to prevent any errors in the game)
internalXnaTexture = new Texture2D(BaseGame.Device,
16, 16, 0, ResourceUsage.None,
SurfaceFormat.Dxt1,
ResourceManagementMode.Automatic);
Log.Write("Failed to load texture " + fullFilename +
", will use empty texture! Error: " + ex.ToString());
} // else
#endif
} // catch (ex)
} // Load()
#endregion
#region Render on screen
///
/// Render texture at rect directly on screen using pixelRect.
///
/// Rectangle
/// Pixel rectangle
public void RenderOnScreen(Rectangle rect, Rectangle pixelRect)
{
SpriteHelper.AddSpriteToRender(this, rect, pixelRect);
} // RenderOnScreen(rect, pixelRect)
///
/// Render on screen
///
/// Rectangle
/// Pixel x
/// Pixel y
/// Pixel width
/// Pixel height
public void RenderOnScreen(Rectangle rect,
int pixelX, int pixelY, int pixelWidth, int pixelHeight)
{
SpriteHelper.AddSpriteToRender(this, rect,
new Rectangle(pixelX, pixelY, pixelWidth, pixelHeight));
} // RenderOnScreen(rect, pixelX, pixelY)
///
/// Render on screen
///
/// Position
public void RenderOnScreen(Point pos)
{
SpriteHelper.AddSpriteToRender(this,
new Rectangle(pos.X, pos.Y, texWidth, texHeight),
new Rectangle(0, 0, texWidth, texHeight));
} // RenderOnScreen(pos)
///
/// Render on screen
///
/// Render rectangle
public void RenderOnScreen(Rectangle renderRect)
{
SpriteHelper.AddSpriteToRender(this,
renderRect, GfxRectangle);
} // RenderOnScreen(renderRect)
///
/// Render on screen relative for 1024x640 (16:9) graphics.
///
/// Rel x
/// Rel y
/// Pixel rectangle
public void RenderOnScreenRelative16To9(int relX, int relY,
Rectangle pixelRect)
{
SpriteHelper.AddSpriteToRender(this,
BaseGame.CalcRectangle(
relX, relY, pixelRect.Width, pixelRect.Height),
pixelRect);
} // RenderOnScreenRelative(relX, relY, pixelRect)
///
/// Render on screen relative 1024x786 (4:3)
///
/// Rel x
/// Rel y
/// Pixel rectangle
public void RenderOnScreenRelative4To3(int relX, int relY,
Rectangle pixelRect)
{
SpriteHelper.AddSpriteToRender(this,
BaseGame.CalcRectangleKeep4To3(
relX, relY, pixelRect.Width, pixelRect.Height),
pixelRect);
} // RenderOnScreenRelative4To3(relX, relY, pixelRect)
///
/// Render on screen relative for 1600px width graphics.
///
/// Rel x
/// Rel y
/// Pixel rectangle
public void RenderOnScreenRelative1600(
int relX, int relY, Rectangle pixelRect)
{
SpriteHelper.AddSpriteToRender(this,
BaseGame.CalcRectangle1600(
relX, relY, pixelRect.Width, pixelRect.Height),
pixelRect);
} // RenderOnScreenRelative1600(relX, relY, pixelRect)
///
/// Render texture at rect directly on screen using texture cordinates.
/// This method allows to render with specific color and alpha values.
///
/// Rectangle
/// Pixel rectangle
/// Color
public void RenderOnScreen(Rectangle rect, Rectangle pixelRect,
Color color)
{
SpriteHelper.AddSpriteToRender(this, rect, pixelRect, color);
} // RenderOnScreen(rect, pixelRect, color)
///
/// Render on screen
///
/// Rectangle
/// Pixel rectangle
/// Color
/// Blend mode
public void RenderOnScreen(Rectangle rect, Rectangle pixelRect,
Color color, SpriteBlendMode blendMode)
{
SpriteHelper.AddSpriteToRender(this, rect, pixelRect, color, blendMode);
} // RenderOnScreen(rect, pixelRect, color)
#endregion
#region Rendering on screen with rotation
///
/// Render on screen with rotation
///
/// Position
/// Pixel rectangle
/// Rotation
public void RenderOnScreenWithRotation(
Rectangle rect, Rectangle pixelRect,
float rotation, Vector2 rotationPoint)
{
//Rectangle rect =
// new Rectangle(pos.X, pos.Y, pixelRect.Width, pixelRect.Height);
SpriteHelper.AddSpriteToRender(this,
rect, pixelRect, rotation,
//new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2));
rotationPoint);
} // RenderOnScreenWithRotation(pos, pixelRect, rotation)
#endregion
#region To string
///
/// To string
///
public override string ToString()
{
return "Texture(filename=" + texFilename +
", width=" + texWidth +
", height=" + texHeight +
", xnaTexture=" + (internalXnaTexture != null ? "valid" : "null") +
", hasAlpha=" + hasAlpha + ")";
} // ToString()
#endregion
#region Unit Testing
#if DEBUG
///
/// Test textures
///
public static void TestRenderTexture()
{
Texture testTexture = null;
TestGame.Start("TestTextures",
delegate
{
testTexture = new Texture("SpaceBackground");
},
delegate
{
testTexture.RenderOnScreen(
new Rectangle(100, 100, 256, 256),
testTexture.GfxRectangle,
Color.White, SpriteBlendMode.Additive);
// Use alpha blending
testTexture.RenderOnScreen(
new Rectangle(Input.MousePos.X, Input.MousePos.Y, 512, 512),
testTexture.GfxRectangle, Color.Red, SpriteBlendMode.Additive);
});
} // TestTextures()
#endif
#endregion
} // class Texture
} // namespace XnaGraphicEngine.Graphics