using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MLEM.Extensions {
///
/// A set of extensions for dealing with
///
public static class TextureExtensions {
///
/// Returns a new instance of which allows easily managing a texture's data with texture coordinates rather than indices.
/// When this is used in a using statement, the texture data is automatically stored back in the texture at the end.
///
/// The texture whose data to get
/// The texture's data
public static TextureData GetTextureData(this Texture2D texture) {
return new TextureData(texture);
}
///
/// A struct that represents the data of a texture, accessed through .
///
public class TextureData : IDisposable {
private readonly Texture2D texture;
private readonly Color[] data;
private bool dirty;
///
/// Returns the color at the given x,y position of the texture, where 0,0 represents the bottom left.
///
/// The x coordinate of the texture location
/// The y coordinate of the texture location
public Color this[int x, int y] {
get => this.data[this.ToIndex(x, y)];
set {
var index = this.ToIndex(x, y);
if (this.data[index] != value) {
this.data[index] = value;
this.dirty = true;
}
}
}
///
public Color this[Point point] {
get => this[point.X, point.Y];
set => this[point.X, point.Y] = value;
}
///
/// Creates a new texture data instance for the given texture.
/// Note that this can more easily be invoked using .
///
/// The texture whose data to get
public TextureData(Texture2D texture) {
this.texture = texture;
this.data = new Color[texture.Width * texture.Height];
this.texture.GetData(this.data);
}
///
/// Stores this texture data back into the underlying texture
///
public void Store() {
if (this.dirty) {
this.texture.SetData(this.data);
this.dirty = false;
}
}
///
/// Converts the given x,y texture coordinate to the corresponding index in the array.
///
/// The x coordinate
/// The y coordinate
/// The corresponding texture array index
/// If the given coordinate is out of bounds
public int ToIndex(int x, int y) {
if (!this.IsInBounds(x, y))
throw new ArgumentException();
return y * this.texture.Width + x;
}
///
/// Converts the given index from the array into the corresponding x,y texture coordinate.
///
/// The texture array index
/// The corresponding texture coordinate
/// If the given index is out of bounds
public Point FromIndex(int index) {
if (index < 0 || index >= this.data.Length)
throw new ArgumentException();
return new Point(index % this.texture.Width, index / this.texture.Width);
}
///
/// Checks if the given x,y texture coordinates is within the bounds of the underlying texture.
///
/// The x coordinate
/// The y coordinate
/// Whether the given coordinate is within bounds of the underlying texture
public bool IsInBounds(int x, int y) {
return x >= 0 && y >= 0 && x < this.texture.Width && y < this.texture.Height;
}
///
public void Dispose() {
this.Store();
}
}
}
}