Update arrangement logic for containers, remove position property from Rect, add Size property to IElement.

This commit is contained in:
2025-06-19 15:08:23 +02:00
parent e499691714
commit 6affded730
9 changed files with 56 additions and 23 deletions

View File

@@ -67,9 +67,9 @@ public class TestGame : Game
_particleSystem!.RestartEmitter(_emitterId); _particleSystem!.RestartEmitter(_emitterId);
} }
if (Input.KeyboardKeyJustPressed(KeyboardKey.One)) if (Input.IsActionPressed("accept"))
{ {
_container.AddChild(new RectangleWidget(new Rect(Vector2.Zero, 32.0f, 32.0f), MathUtils.RandomColor())); _container.AddChild(new RectangleWidget(new Rect(32.0f, 32.0f), MathUtils.RandomColor()));
} }
if (Input.IsMouseButtonDown(MouseButton.Left)) if (Input.IsMouseButtonDown(MouseButton.Left))
@@ -117,5 +117,5 @@ public class TestGame : Game
private ResourceRef<Sound> _sound; private ResourceRef<Sound> _sound;
private ResourceRef<Texture2d> _icon; private ResourceRef<Texture2d> _icon;
private HorizontalContainer _container = new(spacing: 64.0f); private HorizontalContainer _container = new(spacing: 8.0f);
} }

View File

@@ -134,6 +134,9 @@ namespace Voile.Input
new KeyInputAction(KeyboardKey.D), new KeyInputAction(KeyboardKey.D),
new KeyInputAction(KeyboardKey.Right), new KeyInputAction(KeyboardKey.Right),
]); ]);
AddInputMapping("accept", [
new KeyInputAction(KeyboardKey.Enter),
]);
} }
protected bool TryGetInputMappings(string forAction, [NotNullWhen(true)] out List<IInputAction>? inputActions) protected bool TryGetInputMappings(string forAction, [NotNullWhen(true)] out List<IInputAction>? inputActions)

View File

@@ -9,6 +9,7 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
{ {
public IReadOnlyList<IElement> Children => _children; public IReadOnlyList<IElement> Children => _children;
public Vector2 Position { get; set; } public Vector2 Position { get; set; }
public Rect Size { get; set; } = Rect.Zero;
public Container() public Container()
{ {

View File

@@ -1,3 +1,4 @@
using System.Numerics;
using Voile.Rendering; using Voile.Rendering;
namespace Voile.UI.Containers; namespace Voile.UI.Containers;
@@ -19,15 +20,20 @@ public class HorizontalContainer : Container, IRenderableElement
public override void Arrange() public override void Arrange()
{ {
int i = 0; float currentX = Position.X;
foreach (var child in Children)
{
var pos = Position;
pos.X += i * Spacing;
for (int i = 0; i < Children.Count; i++)
{
var child = Children[i];
var pos = new Vector2(currentX, Position.Y);
child.Position = pos; child.Position = pos;
i++; currentX += child.Size.Width;
if (i < Children.Count - 1)
{
currentX += Spacing;
}
} }
} }

View File

@@ -1,3 +1,4 @@
using System.Numerics;
using Voile.Rendering; using Voile.Rendering;
namespace Voile.UI.Containers; namespace Voile.UI.Containers;
@@ -19,15 +20,20 @@ public class VerticalContainer : Container, IRenderableElement
public override void Arrange() public override void Arrange()
{ {
int i = 0; float currentY = Position.Y;
foreach (var child in Children)
{
var pos = Position;
pos.Y += i * Spacing;
for (int i = 0; i < Children.Count; i++)
{
var child = Children[i];
var pos = new Vector2(Position.X, currentY);
child.Position = pos; child.Position = pos;
i++; currentY += child.Size.Height;
if (i < Children.Count - 1)
{
currentY += Spacing;
}
} }
} }

View File

@@ -7,6 +7,7 @@ namespace Voile.UI;
public interface IElement public interface IElement
{ {
public Vector2 Position { get; set; } public Vector2 Position { get; set; }
public Rect Size { get; set; }
} }
public interface IParentableElement public interface IParentableElement
@@ -15,6 +16,14 @@ public interface IParentableElement
public void AddChild(IElement child); public void AddChild(IElement child);
} }
public interface IResizeableElement
{
/// <summary>
/// Get a minimum rectangle size for this element.
/// </summary>
public abstract Rect MinimumRect { get; }
}
public interface IUpdatableElement public interface IUpdatableElement
{ {
void Update(); void Update();

View File

@@ -1,8 +1,9 @@
using System.Numerics;
namespace Voile.UI; namespace Voile.UI;
/// <summary> /// <summary>
/// Represents a rectangle. Used to determine widget confines for UI layout. /// Represents a rectangle. Used to determine widget confines for UI layout.
/// </summary> /// </summary>
public record Rect(Vector2 Position, float Width, float Height); public record Rect(float Width = 0.0f, float Height = 0.0f)
{
public static Rect Zero => new Rect(0.0f, 0.0f);
}

View File

@@ -18,7 +18,7 @@ public enum ButtonState
public class Button : Widget public class Button : Widget
{ {
public string Label { get; set; } = "Button"; public string Label { get; set; } = "Button";
public override Rect MinimumRect => new Rect(Position, Width: 128.0f, Height: 64.0f); public override Rect MinimumRect => new Rect(Width: 128.0f, Height: 64.0f);
public Button(string label, Action pressedAction) public Button(string label, Action pressedAction)
{ {

View File

@@ -7,11 +7,12 @@ namespace Voile.UI.Widgets;
/// <summary> /// <summary>
/// A base class for all UI widgets. /// A base class for all UI widgets.
/// </summary> /// </summary>
public abstract class Widget : IElement, IRenderableElement, IInputElement public abstract class Widget : IElement, IRenderableElement, IInputElement, IResizeableElement, IUpdatableElement
{ {
public bool Visible { get; set; } = true; public bool Visible { get; set; } = true;
public bool IgnoreInput { get; set; } public bool IgnoreInput { get; set; }
public Vector2 Position { get; set; } = Vector2.Zero; public Vector2 Position { get; set; } = Vector2.Zero;
public Rect Size { get; set; } = new();
public Widget() public Widget()
{ {
@@ -23,9 +24,7 @@ public abstract class Widget : IElement, IRenderableElement, IInputElement
Position = position; Position = position;
} }
/// <summary> /// </inheritdoc>
/// Get a minimum rectangle size for this widget.
/// </summary>
public abstract Rect MinimumRect { get; } public abstract Rect MinimumRect { get; }
/// <summary> /// <summary>
@@ -38,4 +37,12 @@ public abstract class Widget : IElement, IRenderableElement, IInputElement
/// </summary> /// </summary>
/// <param name="action">An input action this widget received.</param> /// <param name="action">An input action this widget received.</param>
public abstract void Input(IInputAction action); public abstract void Input(IInputAction action);
public void Update()
{
if (Size == Rect.Zero)
{
Size = MinimumRect;
}
}
} }