96 lines
2.7 KiB
C#
96 lines
2.7 KiB
C#
using System.Numerics;
|
|
using Voile.Rendering;
|
|
|
|
namespace Voile.UI;
|
|
|
|
public abstract class UIElement : IElement, IRenderableElement, IResizeableElement, IUpdatableElement, IAnchorableElement
|
|
{
|
|
public bool Visible { get; set; } = true;
|
|
public bool IgnoreInput { get; set; } = false;
|
|
public Vector2 LocalPosition { get; set; } = Vector2.Zero;
|
|
public Vector2 GlobalPosition => _parent?.GlobalPosition + LocalPosition ?? LocalPosition;
|
|
|
|
public Rect Size
|
|
{
|
|
get => _size;
|
|
set
|
|
{
|
|
_size = value;
|
|
|
|
if (value.Width < MinimumSize.Width)
|
|
{
|
|
_size.Width = MinimumSize.Width;
|
|
}
|
|
|
|
if (value.Height < MinimumSize.Height)
|
|
{
|
|
_size.Height = MinimumSize.Height;
|
|
}
|
|
|
|
MarkDirty();
|
|
}
|
|
}
|
|
public Vector2 AnchorOffset { get; set; } = Vector2.Zero;
|
|
public Anchor Anchor { get; set; } = Anchor.TopLeft;
|
|
|
|
public abstract Rect MinimumSize { get; }
|
|
public bool Dirty => _dirty;
|
|
|
|
public virtual void MarkDirty() => _dirty = true;
|
|
|
|
public void SetParent(UIElement parent)
|
|
{
|
|
_parent = parent;
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (!_dirty) return;
|
|
_dirty = false;
|
|
|
|
if (Size == Rect.Zero)
|
|
Size = MinimumSize;
|
|
|
|
OnUpdate();
|
|
|
|
if (_parent is not null && _parent.Size != Rect.Zero)
|
|
{
|
|
ApplyAnchor(_parent.GlobalPosition, _parent.Size);
|
|
}
|
|
}
|
|
|
|
public abstract void Render(RenderSystem renderer, Style style);
|
|
protected abstract void OnUpdate();
|
|
|
|
public void DrawSize(RenderSystem renderer)
|
|
{
|
|
renderer.SetTransform(GlobalPosition, Vector2.Zero);
|
|
renderer.DrawRectangleOutline(new Vector2(Size.Width, Size.Height), Color.Red, 2.0f);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines if this <see cref="UIElement"/> contains a point within its confines.
|
|
/// </summary>
|
|
/// <param name="pointPosition">A global position of the point.</param>
|
|
/// <returns>True if the point is inside the widget; otherwise, false.</returns>
|
|
public bool ContainsPoint(Vector2 point)
|
|
{
|
|
return point.X >= GlobalPosition.X && point.Y >= GlobalPosition.Y &&
|
|
point.X <= GlobalPosition.X + Size.Width &&
|
|
point.Y <= GlobalPosition.Y + Size.Height;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Applies this <see cref="UIElement"/> anchor.
|
|
/// </summary>
|
|
public virtual void ApplyAnchor(Vector2 parentPosition, Rect parentRect)
|
|
{
|
|
LocalPosition = Anchor.Calculate(parentPosition, parentRect, Size) + new Vector2(AnchorOffset.X, AnchorOffset.Y);
|
|
}
|
|
|
|
private bool _dirty = true;
|
|
private Rect _size = Rect.Zero;
|
|
|
|
private UIElement? _parent;
|
|
}
|