//-----------------------------------------------------------------------------
// Texture.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.IO;
using RacingGame.Helpers;
namespace RacingGame.Graphics
{
///
/// Texture class helping you with using DirectX Textures and handling
/// possible errors that can happen while loading (stupid DirectX
/// error messages telling you absolutely nothing, so a lot of pre-checks
/// help you determinate the error before even calling DirectX methods).
///
public class Texture : IDisposable
{
public static SpriteBatch alphaSprite;
public static SpriteBatch additiveSprite;
///
/// Texture filename
///
protected string texFilename = "";
///
/// Get filename of texture.
///
public string Filename
{
get { return texFilename; }
}
///
/// Size of texture
///
protected int texWidth, texHeight;
///
/// Width of texture
///
public int Width
{
get
{
return texWidth;
}
}
///
/// Height of texture
///
public int Height
{
get
{
return texHeight;
}
}
///
/// Gfx rectangle
///
/// Rectangle
public Rectangle GfxRectangle
{
get
{
return new Rectangle(0, 0, texWidth, texHeight);
}
}
///
/// Size of half a pixel, will be calculated when size is set.
///
private Vector2 precaledHalfPixelSize = Vector2.Zero;
///
/// 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;
}
}
///
/// Calc half pixel size
///
protected void CalcHalfPixelSize()
{
precaledHalfPixelSize = new Vector2(
(1.0f / texWidth) / 2.0f,
(1.0f / texHeight) / 2.0f);
}
///
/// XNA Framework Graphic Texture
///
protected Texture2D internalXnaTexture;
///
/// XNA Framework texture
///
public virtual Texture2D XnaTexture
{
get
{
return internalXnaTexture;
}
}
///
/// 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;
}
}
///
/// Has alpha?
///
private bool hasAlpha;
///
/// Has texture alpha information?
///
public bool HasAlphaPixels
{
get
{
return hasAlpha;
}
}
///
/// Create texture from a given filename.
///
/// Set filename, must be relative and be a
/// valid file in the Textures directory.
public Texture(string setFilename)
{
if (alphaSprite == null)
alphaSprite = new SpriteBatch(BaseGame.Device);
if (additiveSprite == null)
additiveSprite = new SpriteBatch(BaseGame.Device);
if (String.IsNullOrEmpty(setFilename))
throw new ArgumentNullException(nameof(setFilename),
"Unable to create texture without valid filename.");
// Set content name (cut off extension!)
texFilename = Path.GetFileNameWithoutExtension(setFilename);
string fullFilename =
Path.Combine(Directories.ContentDirectory, "Textures", texFilename);
// 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 and Dxt5 textures.
hasAlpha = (internalXnaTexture.Format == SurfaceFormat.Dxt5 ||
internalXnaTexture.Format == SurfaceFormat.Dxt3);
loaded = true;
CalcHalfPixelSize();
}
///
/// Create texture, protected version for derived classes.
///
protected Texture()
{
}
///
/// Create texture by just assigning a Texture2D.
///
/// Tex
public Texture(Texture2D tex)
{
if (alphaSprite == null)
alphaSprite = new SpriteBatch(BaseGame.Device);
if (additiveSprite == null)
additiveSprite = new SpriteBatch(BaseGame.Device);
if (tex == null)
throw new ArgumentNullException(nameof(tex));
internalXnaTexture = tex;
// Get info from the texture directly.
texWidth = internalXnaTexture.Width;
texHeight = internalXnaTexture.Height;
loaded = true;
// We will use alpha for Dxt3 and Dxt5 textures
hasAlpha = (internalXnaTexture.Format == SurfaceFormat.Dxt5 ||
internalXnaTexture.Format == SurfaceFormat.Dxt3);
CalcHalfPixelSize();
}
///
/// Dispose
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Dispose
///
/// Disposing
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (internalXnaTexture != null)
internalXnaTexture.Dispose();
internalXnaTexture = null;
}
loaded = false;
}
///
/// Render texture at rect directly on screen using pixelRect.
///
/// Rectangle
/// Pixel rectangle
public void RenderOnScreen(Rectangle rect, Rectangle pixelRect)
{
alphaSprite.Draw(internalXnaTexture, rect, pixelRect, Color.White);
//SpriteHelper.AddSpriteToRender(this, 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)
{
alphaSprite.Draw(internalXnaTexture, rect, new Rectangle(pixelX, pixelY,
pixelWidth, pixelHeight), Color.White);
}
///
/// Render on screen
///
/// Position
public void RenderOnScreen(Point pos)
{
alphaSprite.Draw(internalXnaTexture,
new Rectangle(pos.X, pos.Y, texWidth, texHeight),
new Rectangle(0, 0, texWidth, texHeight), Color.White);
}
///
/// Render on screen
///
/// Render rectangle
public void RenderOnScreen(Rectangle renderRect)
{
alphaSprite.Draw(internalXnaTexture, renderRect, GfxRectangle, Color.White);
//SpriteHelper.AddSpriteToRender(this,
// renderRect, GfxRectangle);
}
///
/// Render on screen relative for 1024x640 (16:9) graphics.
///
/// Rel x
/// Rel y
/// Pixel rectangle
public void RenderOnScreenRelative16To9(int relX, int relY,
Rectangle pixelRect)
{
alphaSprite.Draw(internalXnaTexture, BaseGame.CalcRectangle(
relX, relY, pixelRect.Width, pixelRect.Height),
pixelRect, Color.White);
//SpriteHelper.AddSpriteToRender(this,
// BaseGame.CalcRectangle(
// relX, relY, pixelRect.Width, pixelRect.Height),
// pixelRect);
}
///
/// Render on screen relative 1024x786 (4:3)
///
/// Rel x
/// Rel y
/// Pixel rectangle
public void RenderOnScreenRelative4To3(int relX, int relY,
Rectangle pixelRect)
{
alphaSprite.Draw(internalXnaTexture, BaseGame.CalcRectangleKeep4To3(
relX, relY, pixelRect.Width, pixelRect.Height),
pixelRect, Color.White);
//SpriteHelper.AddSpriteToRender(this,
// BaseGame.CalcRectangleKeep4To3(
// relX, relY, pixelRect.Width, pixelRect.Height),
// pixelRect);
}
///
/// Render on screen relative for 1600px width graphics.
///
/// Rel x
/// Rel y
/// Pixel rectangle
public void RenderOnScreenRelative1600(
int relX, int relY, Rectangle pixelRect)
{
alphaSprite.Draw(internalXnaTexture, BaseGame.CalcRectangle1600(
relX, relY, pixelRect.Width, pixelRect.Height),
pixelRect, Color.White);
//SpriteHelper.AddSpriteToRender(this,
// BaseGame.CalcRectangle1600(
// relX, relY, pixelRect.Width, pixelRect.Height),
// 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)
{
alphaSprite.Draw(internalXnaTexture, rect, pixelRect, color);
//SpriteHelper.AddSpriteToRender(this, rect, pixelRect, color);
}
///
/// Render on screen
///
/// Rectangle
/// Pixel rectangle
/// Color
/// Blend mode
public void RenderOnScreen(Rectangle rect, Rectangle pixelRect,
Color color, BlendState blendState)
{
if (blendState == BlendState.Additive)
additiveSprite.Draw(internalXnaTexture, rect, pixelRect, color);
else
alphaSprite.Draw(internalXnaTexture, rect, pixelRect, color);
//SpriteHelper.AddSpriteToRender(this, rect, pixelRect, color, blendState);
}
///
/// Render on screen with rotation
///
///
/// Pixel rectangle
/// Rotation
///
public void RenderOnScreenWithRotation(
Rectangle rect, Rectangle pixelRect,
float rotation, Vector2 rotationPoint)
{
alphaSprite.Draw(internalXnaTexture, rect, pixelRect, Color.White, rotation,
rotationPoint, SpriteEffects.None, 0);
}
///
/// To string
///
public override string ToString()
{
return "Texture(filename=" + texFilename +
", width=" + texWidth +
", height=" + texHeight +
", xnaTexture=" + (internalXnaTexture != null ? "valid" : "null") + ")";
}
}
}