using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MLEM.Graphics;
using MLEM.Misc;
using MLEM.Textures;
using MLEM.Ui.Style;
namespace MLEM.Ui.Elements {
///
/// An image element to be used inside of a .
/// An image is simply an element that displays a supplied and optionally allows for the texture region to remain at its original aspect ratio, regardless of the element's size.
///
public class Image : Element {
///
/// The color to render the image at
///
public StyleProp Color;
///
/// A callback to retrieve the that this image should render.
/// This can be used if the image changes frequently.
///
public TextureCallback GetTextureCallback;
///
/// The texture that this should render
///
public TextureRegion Texture {
get {
if (this.GetTextureCallback != null)
this.Texture = this.GetTextureCallback(this);
return this.texture;
}
set {
if (this.texture != value) {
this.texture = value;
this.IsHidden = this.texture == null;
if (this.scaleToImage)
this.SetAreaDirty();
}
}
}
///
/// Whether this image element's should be based on the size of the given.
/// Note that, when scaling to the image's size, the is also taken into account.
///
public bool ScaleToImage {
get => this.scaleToImage;
set {
if (this.scaleToImage != value) {
this.scaleToImage = value;
this.SetAreaDirty();
}
}
}
///
/// Whether to cause the to be rendered at its proper aspect ratio.
/// If this is false, the image will be stretched according to this component's size.
///
public bool MaintainImageAspect = true;
///
/// The that the texture should be rendered with
///
public SpriteEffects ImageEffects = SpriteEffects.None;
///
/// The scale that the image should be rendered with
///
public Vector2 ImageScale = Vector2.One;
///
/// The rotation that the image should be rendered with.
/// Note that increased rotation does not increase this component's size, even if the rotated texture would go out of bounds of this component.
///
public float ImageRotation;
private bool scaleToImage;
private TextureRegion texture;
///
/// Creates a new image with the given settings
///
/// The image's anchor
/// The image's size
/// The texture the image should render
/// Whether this image's size should be based on the texture's size
public Image(Anchor anchor, Vector2 size, TextureRegion texture, bool scaleToImage = false) : base(anchor, size) {
this.Texture = texture;
this.scaleToImage = scaleToImage;
this.CanBeSelected = false;
this.CanBeMoused = false;
}
///
public Image(Anchor anchor, Vector2 size, TextureCallback getTextureCallback, bool scaleToImage = false) : base(anchor, size) {
this.GetTextureCallback = getTextureCallback;
this.Texture = getTextureCallback(this);
this.scaleToImage = scaleToImage;
this.CanBeSelected = false;
this.CanBeMoused = false;
}
///
protected override Vector2 CalcActualSize(RectangleF parentArea) {
return this.Texture != null && this.scaleToImage ? this.Texture.Size.ToVector2() * this.Scale : base.CalcActualSize(parentArea);
}
///
public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
if (this.Texture == null)
return;
var center = new Vector2(this.Texture.Width / 2F, this.Texture.Height / 2F);
var color = this.Color.OrDefault(Microsoft.Xna.Framework.Color.White) * alpha;
if (this.MaintainImageAspect) {
var scale = Math.Min(this.DisplayArea.Width / this.Texture.Width, this.DisplayArea.Height / this.Texture.Height);
var imageOffset = new Vector2(this.DisplayArea.Width / 2F - this.Texture.Width * scale / 2, this.DisplayArea.Height / 2F - this.Texture.Height * scale / 2);
batch.Draw(this.Texture, this.DisplayArea.Location + center * scale + imageOffset, color, this.ImageRotation, center, scale * this.ImageScale, this.ImageEffects, 0);
} else {
var scale = new Vector2(1F / this.Texture.Width, 1F / this.Texture.Height) * this.DisplayArea.Size;
batch.Draw(this.Texture, this.DisplayArea.Location + center * scale, color, this.ImageRotation, center, scale * this.ImageScale, this.ImageEffects, 0);
}
base.Draw(time, batch, alpha, context);
}
///
/// A delegate method used for
///
/// The current image element
public delegate TextureRegion TextureCallback(Image image);
}
}