Add container nesting.

This commit is contained in:
2025-06-19 14:50:05 +02:00
parent 806c9cc1d4
commit e499691714
8 changed files with 113 additions and 17 deletions

View File

@@ -55,12 +55,7 @@ public class TestGame : Game
Input.AddInputMapping("reload", new IInputAction[] { new KeyInputAction(KeyboardKey.R) });
_emitterId = _particleSystem.CreateEmitter(Renderer.WindowSize / 2, _fireEffect);
_uiSystem.AddElement(new VerticalContainer(new()
{
new Label("Hello, I'm a label!", _font),
new Label("I'm also a label, except I'm located slightly lower!", _font),
new Label("I hope a VerticalContainer works.", _font)
}, 64.0f));
_uiSystem.AddElement(_container);
}
@@ -74,7 +69,7 @@ public class TestGame : Game
if (Input.KeyboardKeyJustPressed(KeyboardKey.One))
{
_particleSystem.CreateEmitter(Input.GetMousePosition(), _fireEffect);
_container.AddChild(new RectangleWidget(new Rect(Vector2.Zero, 32.0f, 32.0f), MathUtils.RandomColor()));
}
if (Input.IsMouseButtonDown(MouseButton.Left))
@@ -121,4 +116,6 @@ public class TestGame : Game
private ResourceRef<Font> _font;
private ResourceRef<Sound> _sound;
private ResourceRef<Texture2d> _icon;
private HorizontalContainer _container = new(spacing: 64.0f);
}

View File

@@ -1,27 +1,41 @@
using System.Numerics;
using Voile.UI.Widgets;
namespace Voile.UI.Containers;
/// <summary>
/// A base class for all UI containers, used to position and rendering child <see cref="Widget">s.
/// A base class for all UI containers, used to position and rendering child <see cref="IElement">s.
/// </summary>
public abstract class Container : IElement, IParentableElement
public abstract class Container : IElement, IParentableElement, IUpdatableElement
{
public IReadOnlyList<IElement> Children => _children;
public Vector2 Position { get; set; }
public Container()
{
}
public Container(List<IElement> children)
{
_children = children;
}
public void Update()
{
Arrange();
foreach (var child in _children)
{
if (child is not IUpdatableElement updatable) continue;
updatable.Update();
}
}
public abstract void Arrange();
public void AddChild(IElement child)
{
_children.Add(child);
Update();
}
private List<IElement> _children;
private List<IElement> _children = new();
}

View File

@@ -0,0 +1,42 @@
using Voile.Rendering;
namespace Voile.UI.Containers;
public class HorizontalContainer : Container, IRenderableElement
{
public float Spacing { get; set; } = 16.0f;
public bool Visible { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public HorizontalContainer(List<IElement> children, float spacing = 16.0f) : base(children)
{
Spacing = spacing;
}
public HorizontalContainer(float spacing = 16.0f)
{
Spacing = spacing;
}
public override void Arrange()
{
int i = 0;
foreach (var child in Children)
{
var pos = Position;
pos.X += i * Spacing;
child.Position = pos;
i++;
}
}
public void Render(RenderSystem renderer, Style style)
{
foreach (var child in Children)
{
if (child is not IRenderableElement renderable) continue;
renderable.Render(renderer, style);
}
}
}

View File

@@ -1,5 +1,4 @@
using Voile.Rendering;
using Voile.UI.Widgets;
namespace Voile.UI.Containers;
@@ -8,7 +7,12 @@ public class VerticalContainer : Container, IRenderableElement
public float Spacing { get; set; } = 16.0f;
public bool Visible { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public VerticalContainer(List<IElement> children, float spacing) : base(children)
public VerticalContainer(List<IElement> children, float spacing = 16.0f) : base(children)
{
Spacing = spacing;
}
public VerticalContainer(float spacing = 16.0f)
{
Spacing = spacing;
}

View File

@@ -15,6 +15,11 @@ public interface IParentableElement
public void AddChild(IElement child);
}
public interface IUpdatableElement
{
void Update();
}
public interface IRenderableElement
{
public bool Visible { get; set; }

View File

@@ -25,10 +25,8 @@ public class UISystem : IUpdatableSystem, IRenderableSystem
{
foreach (var element in _elements)
{
if (element is Container container)
{
container.Arrange();
}
if (element is not IUpdatableElement updatable) continue;
updatable.Update();
}
}

View File

@@ -0,0 +1,27 @@
using System.Numerics;
using Voile.Input;
using Voile.Rendering;
namespace Voile.UI.Widgets;
public class RectangleWidget : Widget
{
public override Rect MinimumRect { get; }
public Color Color { get; set; } = Color.White;
public RectangleWidget(Rect minimumRect, Color color)
{
MinimumRect = minimumRect;
Color = color;
}
public override void Input(IInputAction action)
{
throw new NotImplementedException();
}
public override void Render(RenderSystem renderer, Style style)
{
renderer.SetTransform(Position, Vector2.Zero);
renderer.DrawRectangle(new Vector2(MinimumRect.Width, MinimumRect.Height), Color);
}
}

View File

@@ -35,6 +35,15 @@ namespace Voile
return new Vector2((float)x, (float)y);
}
public static Color RandomColor()
{
var r = _random.NextDouble(0.0f, 1.0f);
var g = _random.NextDouble(0.0f, 1.0f);
var b = _random.NextDouble(0.0f, 1.0f);
return new Color((float)r, (float)g, (float)b);
}
public static float EaseOutBack(float x)
{
var c1 = 1.70158f;