Initial implementation of UI anchors, update TestGame.

This commit is contained in:
2025-06-21 22:23:19 +02:00
parent ae1b612524
commit 683656dee8
8 changed files with 148 additions and 20 deletions

View File

@@ -3,10 +3,11 @@ using Voile.Rendering;
namespace Voile.UI.Containers;
// TODO: make Container extend Widget, it already implements similar behaviors.
/// <summary>
/// A base class for all UI containers, used to position and rendering child <see cref="IElement">s.
/// </summary>
public abstract class Container : IElement, IParentableElement, IUpdatableElement, IResizeableElement, IRenderableElement
public abstract class Container : IElement, IParentableElement, IUpdatableElement, IResizeableElement, IRenderableElement, IAnchorableElement
{
/// <inheritdoc />
public IReadOnlyList<IElement> Children => _children;
@@ -44,6 +45,8 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
/// Specifies if this <see cref="Container"/>'s minimum size will be confined to contents.
/// </summary>
public bool ConfineToContents { get; set; } = false;
public Anchor Anchor { get; set; }
public Vector2 AnchorOffset { get; set; }
public Container()
{
@@ -75,6 +78,11 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
{
if (child is not IUpdatableElement updatable) continue;
updatable.Update();
if (child is IAnchorableElement anchorable)
{
anchorable.ApplyAnchor(Position, Size);
}
}
Arrange();
@@ -161,6 +169,38 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
renderer.DrawRectangleOutline(new Vector2(Size.Width, Size.Height), Color.Red, 2.0f);
}
public void ApplyAnchor(Vector2 parentPosition, Rect parentRect)
{
var absoluteOffset = AnchorOffset * new Vector2(Size.Width, Size.Height);
switch (Anchor)
{
case Anchor.TopLeft:
Position = parentPosition - AnchorOffset;
break;
case Anchor.TopCenter:
var topCenterX = parentRect.Width / 2;
var topCenterY = parentPosition.Y;
Position = new Vector2(parentPosition.X + topCenterX, topCenterY) - absoluteOffset;
break;
case Anchor.TopRight:
Position = new Vector2(parentPosition.X + parentRect.Width, parentPosition.Y);
break;
case Anchor.Fill:
Position = parentPosition;
Size = parentRect;
break;
default:
throw new NotImplementedException("This anchor type is not implemented!");
}
MarkDirty();
Update();
}
private List<IElement> _children = new();
private bool _isDirty;
private Rect _size = Rect.Zero;