diff --git a/TestGame/TestGame.cs b/TestGame/TestGame.cs index 92d20cd..d2a9714 100644 --- a/TestGame/TestGame.cs +++ b/TestGame/TestGame.cs @@ -67,9 +67,9 @@ public class TestGame : Game _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)) @@ -117,5 +117,5 @@ public class TestGame : Game private ResourceRef _sound; private ResourceRef _icon; - private HorizontalContainer _container = new(spacing: 64.0f); + private HorizontalContainer _container = new(spacing: 8.0f); } \ No newline at end of file diff --git a/Voile/Source/Input/InputSystem.cs b/Voile/Source/Input/InputSystem.cs index 516f48f..578daca 100644 --- a/Voile/Source/Input/InputSystem.cs +++ b/Voile/Source/Input/InputSystem.cs @@ -134,6 +134,9 @@ namespace Voile.Input new KeyInputAction(KeyboardKey.D), new KeyInputAction(KeyboardKey.Right), ]); + AddInputMapping("accept", [ + new KeyInputAction(KeyboardKey.Enter), + ]); } protected bool TryGetInputMappings(string forAction, [NotNullWhen(true)] out List? inputActions) diff --git a/Voile/Source/UI/Containers/Container.cs b/Voile/Source/UI/Containers/Container.cs index 6709e00..aaabd98 100644 --- a/Voile/Source/UI/Containers/Container.cs +++ b/Voile/Source/UI/Containers/Container.cs @@ -9,6 +9,7 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen { public IReadOnlyList Children => _children; public Vector2 Position { get; set; } + public Rect Size { get; set; } = Rect.Zero; public Container() { diff --git a/Voile/Source/UI/Containers/HorizontalContainer.cs b/Voile/Source/UI/Containers/HorizontalContainer.cs index 95157b9..9b43d90 100644 --- a/Voile/Source/UI/Containers/HorizontalContainer.cs +++ b/Voile/Source/UI/Containers/HorizontalContainer.cs @@ -1,3 +1,4 @@ +using System.Numerics; using Voile.Rendering; namespace Voile.UI.Containers; @@ -19,15 +20,20 @@ public class HorizontalContainer : Container, IRenderableElement public override void Arrange() { - int i = 0; - foreach (var child in Children) - { - var pos = Position; - pos.X += i * Spacing; + float currentX = Position.X; + for (int i = 0; i < Children.Count; i++) + { + var child = Children[i]; + var pos = new Vector2(currentX, Position.Y); child.Position = pos; - i++; + currentX += child.Size.Width; + + if (i < Children.Count - 1) + { + currentX += Spacing; + } } } diff --git a/Voile/Source/UI/Containers/VerticalContainer.cs b/Voile/Source/UI/Containers/VerticalContainer.cs index cd5b023..f090669 100644 --- a/Voile/Source/UI/Containers/VerticalContainer.cs +++ b/Voile/Source/UI/Containers/VerticalContainer.cs @@ -1,3 +1,4 @@ +using System.Numerics; using Voile.Rendering; namespace Voile.UI.Containers; @@ -19,15 +20,20 @@ public class VerticalContainer : Container, IRenderableElement public override void Arrange() { - int i = 0; - foreach (var child in Children) - { - var pos = Position; - pos.Y += i * Spacing; + float currentY = Position.Y; + for (int i = 0; i < Children.Count; i++) + { + var child = Children[i]; + var pos = new Vector2(Position.X, currentY); child.Position = pos; - i++; + currentY += child.Size.Height; + + if (i < Children.Count - 1) + { + currentY += Spacing; + } } } diff --git a/Voile/Source/UI/IElement.cs b/Voile/Source/UI/IElement.cs index 72c3885..e9446c3 100644 --- a/Voile/Source/UI/IElement.cs +++ b/Voile/Source/UI/IElement.cs @@ -7,6 +7,7 @@ namespace Voile.UI; public interface IElement { public Vector2 Position { get; set; } + public Rect Size { get; set; } } public interface IParentableElement @@ -15,6 +16,14 @@ public interface IParentableElement public void AddChild(IElement child); } +public interface IResizeableElement +{ + /// + /// Get a minimum rectangle size for this element. + /// + public abstract Rect MinimumRect { get; } +} + public interface IUpdatableElement { void Update(); diff --git a/Voile/Source/UI/Rect.cs b/Voile/Source/UI/Rect.cs index 84b484e..de1b7ad 100644 --- a/Voile/Source/UI/Rect.cs +++ b/Voile/Source/UI/Rect.cs @@ -1,8 +1,9 @@ -using System.Numerics; - namespace Voile.UI; /// /// Represents a rectangle. Used to determine widget confines for UI layout. /// -public record Rect(Vector2 Position, float Width, float Height); \ No newline at end of file +public record Rect(float Width = 0.0f, float Height = 0.0f) +{ + public static Rect Zero => new Rect(0.0f, 0.0f); +} \ No newline at end of file diff --git a/Voile/Source/UI/Widgets/Button.cs b/Voile/Source/UI/Widgets/Button.cs index 568709d..3598f34 100644 --- a/Voile/Source/UI/Widgets/Button.cs +++ b/Voile/Source/UI/Widgets/Button.cs @@ -18,7 +18,7 @@ public enum ButtonState public class Button : Widget { 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) { diff --git a/Voile/Source/UI/Widgets/Widget.cs b/Voile/Source/UI/Widgets/Widget.cs index 4640aae..33c152a 100644 --- a/Voile/Source/UI/Widgets/Widget.cs +++ b/Voile/Source/UI/Widgets/Widget.cs @@ -7,11 +7,12 @@ namespace Voile.UI.Widgets; /// /// A base class for all UI widgets. /// -public abstract class Widget : IElement, IRenderableElement, IInputElement +public abstract class Widget : IElement, IRenderableElement, IInputElement, IResizeableElement, IUpdatableElement { public bool Visible { get; set; } = true; public bool IgnoreInput { get; set; } public Vector2 Position { get; set; } = Vector2.Zero; + public Rect Size { get; set; } = new(); public Widget() { @@ -23,9 +24,7 @@ public abstract class Widget : IElement, IRenderableElement, IInputElement Position = position; } - /// - /// Get a minimum rectangle size for this widget. - /// + /// public abstract Rect MinimumRect { get; } /// @@ -38,4 +37,12 @@ public abstract class Widget : IElement, IRenderableElement, IInputElement /// /// An input action this widget received. public abstract void Input(IInputAction action); + + public void Update() + { + if (Size == Rect.Zero) + { + Size = MinimumRect; + } + } } \ No newline at end of file