You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
344 lines
12 KiB
C#
344 lines
12 KiB
C#
using System;
|
|
using System.IO;
|
|
|
|
namespace Otter {
|
|
/// <summary>
|
|
/// Class representing a texture. Can perform pixel operations on the CPU, but those will be
|
|
/// pretty slow and shouldn't be used that much.
|
|
/// </summary>
|
|
public class Texture : IDisposable {
|
|
|
|
#region Public Fields
|
|
|
|
/// <summary>
|
|
/// The default setting to use for smoothing textures.
|
|
/// Much easier to set this at the start of a program rather than
|
|
/// adjust the settings for every single texture you use.
|
|
/// </summary>
|
|
public static bool DefaultSmooth = false;
|
|
|
|
#endregion Public Fields
|
|
|
|
#region Internal Fields
|
|
|
|
internal bool needsUpdate = false;
|
|
|
|
internal SFML.Graphics.Texture texture;
|
|
|
|
#endregion Internal Fields
|
|
|
|
#region Private Fields
|
|
|
|
SFML.Graphics.Image image;
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Load a texture from a file path.
|
|
/// </summary>
|
|
/// <param name="source">The file path to load from.</param>
|
|
/// <param name="useCache">Determines if the cache should be checked first.</param>
|
|
public Texture(string source, bool useCache = true) {
|
|
if (useCache) {
|
|
texture = Textures.Load(source);
|
|
}
|
|
else {
|
|
texture = new SFML.Graphics.Texture(source);
|
|
}
|
|
Source = source;
|
|
|
|
texture.Smooth = DefaultSmooth;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a texture from a stream of bytes.
|
|
/// </summary>
|
|
/// <param name="stream">The stream to load from.</param>
|
|
/// <param name="useCache">Determines if the cache should be checked first.</param>
|
|
public Texture(Stream stream, bool useCache = true) {
|
|
if (useCache) {
|
|
texture = Textures.Load(stream);
|
|
}
|
|
else {
|
|
texture = new SFML.Graphics.Texture(stream);
|
|
}
|
|
Source = "stream";
|
|
|
|
texture.Smooth = DefaultSmooth;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new texture from a copy of another texture. No cache option for this.
|
|
/// </summary>
|
|
/// <param name="copy">The texture to copy from.</param>
|
|
public Texture(Texture copy) {
|
|
texture = new SFML.Graphics.Texture(copy.SFMLTexture);
|
|
|
|
Source = copy.Source;
|
|
|
|
texture.Smooth = DefaultSmooth;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a texture from a byte array.
|
|
/// </summary>
|
|
/// <param name="bytes">The byte array to load from.</param>
|
|
/// <param name="useCache">Determines if the cache should be checked first.</param>
|
|
public Texture(byte[] bytes, bool useCache = true) {
|
|
if (useCache) {
|
|
using (MemoryStream ms = new MemoryStream(bytes)) {
|
|
texture = Textures.Load(ms);
|
|
}
|
|
}
|
|
else {
|
|
using (MemoryStream ms = new MemoryStream(bytes)) {
|
|
texture = new SFML.Graphics.Texture(ms);
|
|
}
|
|
}
|
|
Source = "byte array";
|
|
|
|
texture.Smooth = DefaultSmooth;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates an empty texture of width and height. This does not use the cache.
|
|
/// </summary>
|
|
/// <param name="width">The width of the texture.</param>
|
|
/// <param name="height">The height of the texture.</param>
|
|
public Texture(int width, int height) {
|
|
if (width < 0) throw new ArgumentException("Width must be greater than 0.");
|
|
if (height < 0) throw new ArgumentException("Height must be greater than 0.");
|
|
|
|
texture = new SFML.Graphics.Texture((uint)width, (uint)height);
|
|
|
|
Source = width + " x " + height + " texture";
|
|
|
|
texture.Smooth = DefaultSmooth;
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Internal Constructors
|
|
|
|
/// <summary>
|
|
/// Load a texture from an SFML texture.
|
|
/// </summary>
|
|
/// <param name="texture"></param>
|
|
internal Texture(SFML.Graphics.Texture texture) {
|
|
this.texture = texture;
|
|
}
|
|
|
|
#endregion Internal Constructors
|
|
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// The height of the texture.
|
|
/// </summary>
|
|
public int Height {
|
|
get { return (int)texture.Size.Y; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The array of pixels in the texture in bytes.
|
|
/// </summary>
|
|
public byte[] Pixels {
|
|
get {
|
|
CreateImage();
|
|
return image.Pixels;
|
|
}
|
|
set {
|
|
image = new SFML.Graphics.Image((uint)Width, (uint)Height, value);
|
|
Update();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The rectangle created by the Texture's width and height.
|
|
/// </summary>
|
|
public Rectangle Region {
|
|
get { return new Rectangle(0, 0, Width, Height); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines if the source texture is smoothed when transformed.
|
|
/// </summary>
|
|
public bool Smooth { get { return texture.Smooth; } set { texture.Smooth = value; } }
|
|
|
|
/// <summary>
|
|
/// The file path source if the texture was loaded from a file.
|
|
/// </summary>
|
|
public string Source { get; private set; }
|
|
/// <summary>
|
|
/// The width of the Texture.
|
|
/// </summary>
|
|
public int Width {
|
|
get { return (int)texture.Size.X; }
|
|
}
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Internal Properties
|
|
|
|
internal SFML.Graphics.Texture SFMLTexture {
|
|
get { return texture; }
|
|
}
|
|
|
|
#endregion Internal Properties
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Copy pixels from one texture to another using blitting.
|
|
/// </summary>
|
|
/// <param name="from"></param>
|
|
/// <param name="fromX"></param>
|
|
/// <param name="fromY"></param>
|
|
/// <param name="toX"></param>
|
|
/// <param name="toY"></param>
|
|
public void CopyPixels(Texture from, int fromX, int fromY, int toX, int toY) {
|
|
CreateImage();
|
|
from.CreateImage();
|
|
|
|
image.Copy(from.image, (uint)toX, (uint)toY, new SFML.Graphics.IntRect(fromX, fromY, from.Width, from.Height));
|
|
|
|
texture = new SFML.Graphics.Texture(image);
|
|
needsUpdate = true;
|
|
}
|
|
|
|
public void CopyPixels(Texture from, int fromX, int fromY, int fromWidth, int fromHeight, int toX, int toY) {
|
|
CreateImage();
|
|
from.CreateImage();
|
|
|
|
image.Copy(from.image, (uint)toX, (uint)toY, new SFML.Graphics.IntRect(fromX, fromY, fromWidth, fromHeight));
|
|
|
|
texture = new SFML.Graphics.Texture(image);
|
|
needsUpdate = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads the image internally in the texture for image manipulation. This is
|
|
/// handled automatically, but it's exposed so that it can be manually controlled.
|
|
/// </summary>
|
|
/// <param name="forceNewImage">If set to true a new image will always be created instead of only when there is no image.</param>
|
|
public void CreateImage(bool forceNewImage = false) {
|
|
if (image == null || forceNewImage) {
|
|
image = texture.CopyToImage();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the Color from a specific pixel on the texture.
|
|
/// Warning: This is slow!
|
|
/// </summary>
|
|
/// <param name="x">The x coordinate of the pixel to get.</param>
|
|
/// <param name="y">The y coordinate of the pixel to get.</param>
|
|
/// <returns>The Color of the pixel.</returns>
|
|
public Color GetPixel(int x, int y) {
|
|
if (x < 0) throw new ArgumentException("X must be greater or equal to than 0.");
|
|
if (y < 0) throw new ArgumentException("Y must be greater or equal to than 0.");
|
|
|
|
CreateImage();
|
|
|
|
return new Color(image.GetPixel((uint)x, (uint)y));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Save the texture to a file. The supported image formats are bmp, png, tga and jpg.
|
|
/// </summary>
|
|
/// <param name="path">The file path to save to. The type of image is deduced from the extension.</param>
|
|
public void SaveToFile(string path) {
|
|
CreateImage();
|
|
|
|
image.SaveToFile(path);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the color of a specific pixel on the texture.
|
|
/// </summary>
|
|
/// <param name="x">The x coordinate of the pixel.</param>
|
|
/// <param name="y">The y coordinate of the pixel.</param>
|
|
/// <param name="color">The Color to set the pixel to.</param>
|
|
public void SetPixel(int x, int y, Color color) {
|
|
if (x < 0) throw new ArgumentException("X must be greater than 0.");
|
|
if (y < 0) throw new ArgumentException("Y must be greater than 0.");
|
|
if (x > Width) throw new ArgumentException("X must be within the texture width.");
|
|
if (y > Height) throw new ArgumentException("Y must be within the texture width.");
|
|
|
|
CreateImage();
|
|
|
|
image.SetPixel((uint)x, (uint)y, color.SFMLColor);
|
|
//texture = new SFML.Graphics.Texture(image);
|
|
texture.Update(image);
|
|
|
|
needsUpdate = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the color of a rectangle of pixels on the texture.
|
|
/// </summary>
|
|
/// <param name="x">The x coordinate of the rectangle.</param>
|
|
/// <param name="y">The y coordinate of the rectangle.</param>
|
|
/// <param name="width">The width of the rectangle.</param>
|
|
/// <param name="height">The height of the rectangle.</param>
|
|
/// <param name="color">The color of the rectangle.</param>
|
|
public void SetRect(int x, int y, int width, int height, Color color) {
|
|
if (x < 0) throw new ArgumentException("X must be greater than 0.");
|
|
if (y < 0) throw new ArgumentException("Y must be greater than 0.");
|
|
if (width < 0) throw new ArgumentException("Width must be greater than 0.");
|
|
if (height < 0) throw new ArgumentException("Height must be greater than 0.");
|
|
|
|
for (var xx = x; xx < x + width; xx++) {
|
|
for (var yy = y; yy < y + height; yy++) {
|
|
SetPixel(xx, yy, color);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Updates the texture to reflect changes made from SetPixel.
|
|
/// </summary>
|
|
public void Update() {
|
|
if (needsUpdate) {
|
|
texture.Update(image);
|
|
needsUpdate = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the texture with a byte array.
|
|
/// Note: Updates immediately. Probably not the fastest.
|
|
/// </summary>
|
|
/// <param name="bytes">The byte array containing our pixels.</param>
|
|
public void SetBytes(byte[] bytes) {
|
|
texture.Update(bytes);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the texture with a byte array, at the given position and size.
|
|
/// Note: Updates immediately. Probably not the fastest.
|
|
/// </summary>
|
|
/// <param name="bytes">The byte array containing our pixels.</param>
|
|
/// <param name="width">The width of the section we are updating.</param>
|
|
/// <param name="height">The height of the section we are updating.</param>
|
|
/// <param name="x">The X coordinate of the section we are updating.</param>
|
|
/// <param name="y">The Y coordinate of the section we are updating.</param>
|
|
public void SetBytes(byte[] bytes, int width, int height, int x = 0, int y = 0) {
|
|
texture.Update(bytes, (uint)width, (uint)height, (uint)x, (uint)y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispose the SFML texture to clear up memory probably.
|
|
/// Warning: might not want to do this since other Textures might be using the same cached texture!
|
|
/// </summary>
|
|
public void Dispose() {
|
|
SFMLTexture.Dispose();
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
|
|
}
|
|
}
|