// 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 virtual 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