From e499691714d4c5134c823c83ed500475bc9e4562 Mon Sep 17 00:00:00 2001 From: dnesov Date: Thu, 19 Jun 2025 14:50:05 +0200 Subject: [PATCH] Add container nesting. --- TestGame/TestGame.cs | 11 ++--- Voile/Source/UI/Containers/Container.cs | 22 ++++++++-- .../UI/Containers/HorizontalContainer.cs | 42 +++++++++++++++++++ .../Source/UI/Containers/VerticalContainer.cs | 8 +++- Voile/Source/UI/IElement.cs | 5 +++ Voile/Source/UI/UISystem.cs | 6 +-- Voile/Source/UI/Widgets/RectangleWidget.cs | 27 ++++++++++++ Voile/Source/Utils/MathUtils.cs | 9 ++++ 8 files changed, 113 insertions(+), 17 deletions(-) create mode 100644 Voile/Source/UI/Containers/HorizontalContainer.cs create mode 100644 Voile/Source/UI/Widgets/RectangleWidget.cs diff --git a/TestGame/TestGame.cs b/TestGame/TestGame.cs index 96933cf..92d20cd 100644 --- a/TestGame/TestGame.cs +++ b/TestGame/TestGame.cs @@ -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; private ResourceRef _sound; private ResourceRef _icon; + + private HorizontalContainer _container = new(spacing: 64.0f); } \ No newline at end of file diff --git a/Voile/Source/UI/Containers/Container.cs b/Voile/Source/UI/Containers/Container.cs index edc0193..6709e00 100644 --- a/Voile/Source/UI/Containers/Container.cs +++ b/Voile/Source/UI/Containers/Container.cs @@ -1,27 +1,41 @@ using System.Numerics; -using Voile.UI.Widgets; namespace Voile.UI.Containers; /// -/// A base class for all UI containers, used to position and rendering child s. +/// A base class for all UI containers, used to position and rendering child s. /// -public abstract class Container : IElement, IParentableElement +public abstract class Container : IElement, IParentableElement, IUpdatableElement { public IReadOnlyList Children => _children; public Vector2 Position { get; set; } + public Container() + { + + } + public Container(List 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 _children; + private List _children = new(); } \ No newline at end of file diff --git a/Voile/Source/UI/Containers/HorizontalContainer.cs b/Voile/Source/UI/Containers/HorizontalContainer.cs new file mode 100644 index 0000000..95157b9 --- /dev/null +++ b/Voile/Source/UI/Containers/HorizontalContainer.cs @@ -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 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); + } + } +} \ No newline at end of file diff --git a/Voile/Source/UI/Containers/VerticalContainer.cs b/Voile/Source/UI/Containers/VerticalContainer.cs index 8829523..cd5b023 100644 --- a/Voile/Source/UI/Containers/VerticalContainer.cs +++ b/Voile/Source/UI/Containers/VerticalContainer.cs @@ -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 children, float spacing) : base(children) + public VerticalContainer(List children, float spacing = 16.0f) : base(children) + { + Spacing = spacing; + } + + public VerticalContainer(float spacing = 16.0f) { Spacing = spacing; } diff --git a/Voile/Source/UI/IElement.cs b/Voile/Source/UI/IElement.cs index 1baa522..72c3885 100644 --- a/Voile/Source/UI/IElement.cs +++ b/Voile/Source/UI/IElement.cs @@ -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; } diff --git a/Voile/Source/UI/UISystem.cs b/Voile/Source/UI/UISystem.cs index 2f535fa..95a5766 100644 --- a/Voile/Source/UI/UISystem.cs +++ b/Voile/Source/UI/UISystem.cs @@ -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(); } } diff --git a/Voile/Source/UI/Widgets/RectangleWidget.cs b/Voile/Source/UI/Widgets/RectangleWidget.cs new file mode 100644 index 0000000..dbae0b4 --- /dev/null +++ b/Voile/Source/UI/Widgets/RectangleWidget.cs @@ -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); + } +} \ No newline at end of file diff --git a/Voile/Source/Utils/MathUtils.cs b/Voile/Source/Utils/MathUtils.cs index 9f8fcbc..cbb7ccc 100644 --- a/Voile/Source/Utils/MathUtils.cs +++ b/Voile/Source/Utils/MathUtils.cs @@ -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;