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.

379 lines
12 KiB
C#

using SFML.Graphics;
using SFML.System;
using SFML.Window;
namespace Otter {
/// <summary>
/// Graphic type that is used to represent a static image.
/// </summary>
public class Image : Graphic {
#region Static Fields
/// <summary>
/// The amount of points to use when rendering a circle shape.
/// </summary>
public static int CirclePointCount = 24;
#endregion
#region Static Methods
/// <summary>
/// Creates a rectangle.
/// </summary>
/// <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>
/// <returns>A new image containing the rectangle.</returns>
static public Image CreateRectangle(int width, int height, Color color) {
Image img = new Image(width, height);
img.Color = color;
img.Width = width;
img.Height = height;
img.rectWidth = width;
img.rectHeight = height;
img.isShape = true;
img.Batchable = false; // Cant batch rectangles for now
img.OutlineColor = Color.None;
return img;
}
/// <summary>
/// Creates a rectangle the size of the active Game window.
/// </summary>
/// <param name="color">The color of the rectangle.</param>
/// <returns>A new image containing the rectangle.</returns>
static public Image CreateRectangle(Color color) {
int w = Game.Instance.Width;
int h = Game.Instance.Height;
return Image.CreateRectangle(w, h, color);
}
/// <summary>
/// Creates a simple black rectangle the size of the active Game window.
/// </summary>
/// <returns>A new image containing the rectangle.</returns>
static public Image CreateRectangle() {
return Image.CreateRectangle(Color.Black);
}
/// <summary>
/// Creates a rectangle.
/// </summary>
/// <param name="width">The width of the rectangle.</param>
/// <param name="height">The height of the rectangle.</param>
/// <returns>A new image containing the rectangle.</returns>
static public Image CreateRectangle(int width, int height) {
return CreateRectangle(width, height, Color.White);
}
/// <summary>
/// Creates a rectangle.
/// </summary>
/// <param name="size">The width and height of the rectangle.</param>
/// <returns>A new image containing the rectangle.</returns>
static public Image CreateRectangle(int size) {
return CreateRectangle(size, size);
}
/// <summary>
/// Creates a rectangle.
/// </summary>
/// <param name="size">The width and height of the rectangle.</param>
/// <param name="color">The color of the rectangle.</param>
/// <returns>A new image containing the rectangle.</returns>
static public Image CreateRectangle(int size, Color color) {
return CreateRectangle(size, size, color);
}
/// <summary>
/// Create a circle.
/// </summary>
/// <param name="radius">The radius of the circle.</param>
/// <param name="color">The color of the circle.</param>
/// <returns>A new image containing the circle.</returns>
static public Image CreateCircle(int radius, Color color) {
Image img = new Image();
img.Width = radius * 2;
img.Height = radius * 2;
img.Color = color;
img.radius = radius;
img.OutlineColor = Color.None;
img.isCircle = true;
img.isShape = true;
img.Batchable = false;
return img;
}
/// <summary>
/// Create a white circle.
/// </summary>
/// <param name="radius">The radius of the circle.</param>
/// <returns>A new image containing the circle.</returns>
static public Image CreateCircle(int radius) {
return CreateCircle(radius, Color.White);
}
#endregion
#region Public Properties
/// <summary>
/// Defines which area of the Image to show.
/// </summary>
public Rectangle ClippingRegion {
get {
return clippingRegion;
}
set {
clippingRegion = value;
NeedsUpdate = true;
}
}
/// <summary>
/// Flip the texture coordinates on the X axis.
/// </summary>
public bool FlippedX {
get { return flippedX; }
set {
flippedX = value;
NeedsUpdate = true;
}
}
/// <summary>
/// Flip the texture coordinates on the Y axis.
/// </summary>
public bool FlippedY {
get { return flippedY; }
set {
flippedY = value;
NeedsUpdate = true;
}
}
/// <summary>
/// The outline color of the Image (only applies to circles and rectangles.)
/// </summary>
public Color OutlineColor {
get {
if (outlineColor == null) return Color.None;
return outlineColor;
}
set {
OutlineColor.Graphic = null;
outlineColor = value;
outlineColor.Graphic = this;
NeedsUpdate = true;
}
}
/// <summary>
/// The outline thickness of the Image (only applies to circles and rectangles.)
/// </summary>
public float OutlineThickness {
get {
return outlineThickness;
}
set {
outlineThickness = value;
NeedsUpdate = true;
}
}
#endregion
#region Private Fields
bool flippedX;
bool flippedY;
Rectangle clippingRegion;
protected bool
flipX = false,
flipY = false;
bool isCircle;
bool isShape;
// Keep track of radius becuase of outline thickness weirdness.
int radius;
// Keep track of shape w and h because of outline thickness weirdness.
int rectWidth;
int rectHeight;
Color outlineColor;
float outlineThickness;
#endregion
#region Constructors
/// <summary>
/// Creates a new Image using a filepath to a texture.
/// </summary>
/// <param name="source">The filepath of the texture.</param>
/// <param name="clip">Where to clip the texture.</param>
public Image(string source = null) : base() {
SetTexture(new Texture(source));
Initialize();
}
protected Image() : base() {
Initialize();
}
/// <summary>
/// Creates a new Image using a Texture.
/// </summary>
/// <param name="texture">The Texture to use.</param>
public Image(Texture texture) : base() {
SetTexture(texture);
Initialize();
}
/// <summary>
/// Creates a new Image using an AtlasTexture.
/// </summary>
/// <param name="texture">The AtlasTexture to use.</param>
public Image(AtlasTexture texture) : base() {
SetTexture(texture);
Initialize();
}
/// <summary>
/// Creates a new Image using a specified width and height.
/// </summary>
/// <param name="width">The width of the Image.</param>
/// <param name="height">The hight of the Image.</param>
public Image(int width, int height) : base() {
Initialize();
Width = width;
Height = height;
}
#endregion
#region Private Methods
void Initialize() {
Name = "Image";
// Proper sprite batching coming soon.
//Batchable = true;
Width = TextureRegion.Width;
Height = TextureRegion.Height;
ClippingRegion = TextureRegion;
}
protected override void TextureChanged() {
base.TextureChanged();
Width = TextureRegion.Width;
Height = TextureRegion.Height;
ClippingRegion = TextureRegion;
}
protected override void UpdateDrawable() {
base.UpdateDrawable();
if (isCircle) {
var circle = new SFML.Graphics.CircleShape(radius);
circle.OutlineThickness = OutlineThickness;
circle.OutlineColor = OutlineColor.SFMLColor;
circle.FillColor = Color.SFMLColor;
circle.SetPointCount((uint)CirclePointCount);
SFMLDrawable = circle;
Width = (int)circle.GetLocalBounds().Width;
Height = (int)circle.GetLocalBounds().Height;
}
else {
if (isShape) {
var rect = new SFML.Graphics.RectangleShape(new Vector2f(rectWidth, rectHeight));
rect.OutlineColor = OutlineColor.SFMLColor;
rect.OutlineThickness = OutlineThickness;
rect.FillColor = Color.SFMLColor;
SFMLDrawable = rect;
Width = (int)rect.GetLocalBounds().Width;
Height = (int)rect.GetLocalBounds().Height;
}
else {
SFMLVertices.Clear();
float x1, y1, x2, y2, u1, v1, u2, v2, cx1, cy1, cx2, cy2;
cx1 = ClippingRegion.Left;
cy1 = ClippingRegion.Top;
cx2 = ClippingRegion.Right;
cy2 = ClippingRegion.Bottom;
x1 = Util.Max(0, cx1);
u1 = TextureLeft + x1;
if (FlippedX) {
u1 = TextureRegion.Width - u1 + TextureLeft + TextureRegion.Left;
}
y1 = Util.Max(0, cy1);
v1 = TextureTop + y1;
if (FlippedY) {
v1 = TextureRegion.Height - v1 + TextureTop + TextureRegion.Top;
}
x2 = Util.Min(TextureRegion.Right, cx2);
u2 = TextureLeft + x2;
if (FlippedX) {
u2 = TextureRegion.Width - u2 + TextureLeft + TextureRegion.Left;
}
y2 = Util.Min(TextureRegion.Bottom, cy2);
v2 = TextureTop + y2;
if (FlippedY) {
v2 = TextureRegion.Height - v2 + TextureTop + TextureRegion.Top;
}
SFMLVertices.Append(x1, y1, Color, u1, v1);
SFMLVertices.Append(x1, y2, Color, u1, v2);
SFMLVertices.Append(x2, y2, Color, u2, v2);
SFMLVertices.Append(x2, y1, Color, u2, v1);
Width = TextureRegion.Width;
Height = TextureRegion.Height;
}
}
}
#endregion
#region Internal
internal VertexArray GetVertices() {
return SFMLVertices;
}
#endregion
}
}