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.
172 lines
5.2 KiB
C#
172 lines
5.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Otter {
|
|
/// <summary>
|
|
/// Graphic that can render a bunch of static images all at once. Images must use the same
|
|
/// texture as the Decals object in order to be baked together properly.
|
|
/// </summary>
|
|
public class Decals : Graphic {
|
|
|
|
#region Private Fields
|
|
|
|
List<Image> images = new List<Image>();
|
|
|
|
#endregion
|
|
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// If the decals have been baked or not.
|
|
/// </summary>
|
|
public bool Solid { get; private set; }
|
|
|
|
/// <summary>
|
|
/// The number of images in the list.
|
|
/// </summary>
|
|
public int Count {
|
|
get {
|
|
return images.Count;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Constructors
|
|
|
|
/// <summary>
|
|
/// Create a new Decals object using a source file path for a texture.
|
|
/// </summary>
|
|
/// <param name="source">The file path to the texture.</param>
|
|
public Decals(string source) {
|
|
SetTexture(new Texture(source));
|
|
Initialize();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a new Decals object using a Texture.
|
|
/// </summary>
|
|
/// <param name="texture">The Texture to use.</param>
|
|
public Decals(Texture texture) {
|
|
SetTexture(texture);
|
|
Initialize();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a new Decals object using an AtlasTexture.
|
|
/// </summary>
|
|
/// <param name="texture"></param>
|
|
public Decals(AtlasTexture texture) {
|
|
SetTexture(texture);
|
|
Initialize();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private Methods
|
|
|
|
void Initialize() {
|
|
NeedsUpdate = false;
|
|
}
|
|
|
|
protected override void UpdateDrawable() {
|
|
base.UpdateDrawable();
|
|
|
|
SFMLVertices.Clear();
|
|
|
|
float maxX = float.MinValue;
|
|
float minX = float.MaxValue;
|
|
float maxY = float.MinValue;
|
|
float minY = float.MaxValue;
|
|
|
|
foreach (var img in images) {
|
|
img.UpdateDrawableIfNeeded();
|
|
|
|
for (uint i = 0; i < img.GetVertices().VertexCount; i++) {
|
|
var v = img.GetVertices()[i];
|
|
|
|
var transform = SFML.Graphics.Transform.Identity;
|
|
transform.Translate(img.X - img.OriginX, img.Y - img.OriginY);
|
|
transform.Rotate(img.Angle, img.OriginX, img.OriginY);
|
|
transform.Scale(img.ScaleX, img.ScaleY, img.OriginX, img.OriginY);
|
|
|
|
var p = transform.TransformPoint(v.Position.X, v.Position.Y);
|
|
|
|
maxX = Util.Max(maxX, p.X);
|
|
minX = Util.Min(minX, p.X);
|
|
maxY = Util.Max(maxY, p.Y);
|
|
minY = Util.Min(minY, p.Y);
|
|
|
|
SFMLVertices.Append(p.X, p.Y, img.Color, v.TexCoords.X, v.TexCoords.Y);
|
|
}
|
|
}
|
|
|
|
Width = Math.Abs((int)Util.Ceil(maxX - minX));
|
|
Height = Math.Abs((int)Util.Ceil(maxY - minY));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Add an image to the list of decals. Only works if Solid is false.
|
|
/// </summary>
|
|
/// <param name="image">The image to add.</param>
|
|
public void Add(Image image) {
|
|
if (Solid) return;
|
|
if (!image.Batchable) {
|
|
throw new ArgumentException("Non batchable images cannot be baked.");
|
|
}
|
|
if (image.Texture.SFMLTexture != Texture.SFMLTexture) {
|
|
throw new ArgumentException("Images must use the same texture as the Decals object.");
|
|
}
|
|
images.Add(image);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Remove an image from the list of decals. Only works if Solid is false.
|
|
/// </summary>
|
|
/// <param name="image"></param>
|
|
public void Remove(Image image) {
|
|
if (Solid) return;
|
|
images.RemoveIfContains(image);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Erases all images from the list. Only works if Solid is false. Will not immediately show changes
|
|
/// until Bake() is called.
|
|
/// </summary>
|
|
public void Clear() {
|
|
if (Solid) return;
|
|
images.Clear();
|
|
NeedsUpdate = true;
|
|
UpdateDrawableIfNeeded();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bake all the images together for rendering.
|
|
/// </summary>
|
|
public void Bake() {
|
|
if (Count == 0) return; // Don't bake if 0 images.
|
|
if (!Solid) {
|
|
NeedsUpdate = true;
|
|
Solid = true;
|
|
UpdateDrawableIfNeeded();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unbake the images back to an editable form.
|
|
/// </summary>
|
|
public void Unbake() {
|
|
if (Solid) {
|
|
Solid = false;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|