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) }); Input.AddInputMapping("reload", new IInputAction[] { new KeyInputAction(KeyboardKey.R) });
_emitterId = _particleSystem.CreateEmitter(Renderer.WindowSize / 2, _fireEffect); _emitterId = _particleSystem.CreateEmitter(Renderer.WindowSize / 2, _fireEffect);
_uiSystem.AddElement(new VerticalContainer(new() _uiSystem.AddElement(_container);
{
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));
} }
@@ -74,7 +69,7 @@ public class TestGame : Game
if (Input.KeyboardKeyJustPressed(KeyboardKey.One)) 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)) if (Input.IsMouseButtonDown(MouseButton.Left))
@@ -121,4 +116,6 @@ public class TestGame : Game
private ResourceRef<Font> _font; private ResourceRef<Font> _font;
private ResourceRef<Sound> _sound; private ResourceRef<Sound> _sound;
private ResourceRef<Texture2d> _icon; private ResourceRef<Texture2d> _icon;
private HorizontalContainer _container = new(spacing: 64.0f);
} }

View File

@@ -1,27 +1,41 @@
using System.Numerics; using System.Numerics;
using Voile.UI.Widgets;
namespace Voile.UI.Containers; namespace Voile.UI.Containers;
/// <summary> /// <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> /// </summary>
public abstract class Container : IElement, IParentableElement public abstract class Container : IElement, IParentableElement, IUpdatableElement
{ {
public IReadOnlyList<IElement> Children => _children; public IReadOnlyList<IElement> Children => _children;
public Vector2 Position { get; set; } public Vector2 Position { get; set; }
public Container()
{
}
public Container(List<IElement> children) public Container(List<IElement> children)
{ {
_children = 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 abstract void Arrange();
public void AddChild(IElement child) public void AddChild(IElement child)
{ {
_children.Add(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.Rendering;
using Voile.UI.Widgets;
namespace Voile.UI.Containers; namespace Voile.UI.Containers;
@@ -8,7 +7,12 @@ public class VerticalContainer : Container, IRenderableElement
public float Spacing { get; set; } = 16.0f; public float Spacing { get; set; } = 16.0f;
public bool Visible { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } 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; Spacing = spacing;
} }

View File

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

View File

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

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); 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) public static float EaseOutBack(float x)
{ {
var c1 = 1.70158f; var c1 = 1.70158f;