diff --git a/TestGame/TestGame.cs b/TestGame/TestGame.cs index 45f7f0a..0c256d0 100644 --- a/TestGame/TestGame.cs +++ b/TestGame/TestGame.cs @@ -127,22 +127,22 @@ public class TestGame : Game private ResourceRef _sound; private ResourceRef _icon; - // private FlexContainer _container = new(minimumSize: new Rect(64.0f, 64.0f), new()) - // { - // ConfineToContents = false, - // Size = new Rect(500, 300), - // Direction = FlexDirection.Column, - // Justify = JustifyContent.Start, - // Align = AlignItems.Center, - // Wrap = true, - // Gap = 10f - // }; + private FlexContainer _container = new(minimumSize: new Rect(64.0f, 64.0f), new()) + { + Anchor = Anchor.Center, + Size = new Rect(500, 300), + Direction = FlexDirection.Column, + Justify = JustifyContent.Start, + Align = AlignItems.Center, + Wrap = true, + Gap = 10f + }; private Frame _frame = new(); - private HorizontalContainer _container = new(new Rect(128.0f, 64.0f), new(), 16) - { - ConfineToContents = true, - Anchor = Anchor.TopRight, - AnchorOffset = new Vector2(1.0f, 0.0f) - }; + // private VerticalContainer _container = new(new Rect(128.0f, 64.0f), new(), 16) + // { + // ConfineToContents = true, + // Anchor = Anchor.CenterLeft, + // AnchorOffset = new Vector2(0.5f, 0.0f) + // }; } \ No newline at end of file diff --git a/Voile/Source/UI/Containers/Container.cs b/Voile/Source/UI/Containers/Container.cs index 8296057..2c9645e 100644 --- a/Voile/Source/UI/Containers/Container.cs +++ b/Voile/Source/UI/Containers/Container.cs @@ -10,7 +10,7 @@ namespace Voile.UI.Containers; public abstract class Container : UIElement, IParentableElement { /// - public IReadOnlyList Children => _children; + public IReadOnlyList Children => _children; /// /// Specifies if this 's minimum size will be confined to contents. @@ -31,7 +31,7 @@ public abstract class Container : UIElement, IParentableElement MarkDirty(); } - public Container(Rect minimumSize, List children) + public Container(Rect minimumSize, List children) { _minimumSize = minimumSize; _children = children; @@ -50,7 +50,7 @@ public abstract class Container : UIElement, IParentableElement if (child is IAnchorableElement anchorable) { - anchorable.ApplyAnchor(Position, Size); + anchorable.ApplyAnchor(GlobalPosition, Size); } } @@ -80,7 +80,7 @@ public abstract class Container : UIElement, IParentableElement foreach (var child in Children) { - var pos = child.Position; + var pos = child.GlobalPosition; var size = child.Size; minX = MathF.Min(minX, pos.X); @@ -105,15 +105,16 @@ public abstract class Container : UIElement, IParentableElement } } - public void AddChild(IElement child) + public void AddChild(UIElement child) { _children.Add(child); + child.SetParent(this); MarkDirty(); Update(); } - public void RemoveChild(IElement child) + public void RemoveChild(UIElement child) { _children.Remove(child); @@ -130,6 +131,6 @@ public abstract class Container : UIElement, IParentableElement } } - private List _children = new(); + private List _children = new(); private Rect _minimumSize = Rect.Zero; } \ No newline at end of file diff --git a/Voile/Source/UI/Containers/FlexContainer.cs b/Voile/Source/UI/Containers/FlexContainer.cs index d91a758..397f068 100644 --- a/Voile/Source/UI/Containers/FlexContainer.cs +++ b/Voile/Source/UI/Containers/FlexContainer.cs @@ -78,16 +78,16 @@ public class FlexContainer : Container public FlexContainer() : base() { } - public FlexContainer(Rect minimumSize, List children) : base(minimumSize, children) { } + public FlexContainer(Rect minimumSize, List children) : base(minimumSize, children) { } public override void Arrange() { float containerMainSize = (Direction == FlexDirection.Row) ? Size.Width : Size.Height; - float mainPos = (Direction == FlexDirection.Row) ? Position.X : Position.Y; - float crossPos = (Direction == FlexDirection.Row) ? Position.Y : Position.X; + float mainPos = 0.0f; + float crossPos = 0.0f; - List> lines = new(); - List currentLine = new(); + List> lines = new(); + List currentLine = new(); float lineMainSum = 0f; float maxCross = 0f; @@ -136,7 +136,7 @@ public class FlexContainer : Container ? new Vector2(currentMain, alignedCross) : new Vector2(alignedCross, currentMain); - child.Position = childPos; + child.LocalPosition = childPos; currentMain += GetMainSize(childSize) + Gap; } diff --git a/Voile/Source/UI/Containers/GridContainer.cs b/Voile/Source/UI/Containers/GridContainer.cs index c463a9c..7da384c 100644 --- a/Voile/Source/UI/Containers/GridContainer.cs +++ b/Voile/Source/UI/Containers/GridContainer.cs @@ -21,7 +21,7 @@ public class GridContainer : Container /// public float RowSpacing { get; set; } = 16.0f; - public GridContainer(Rect minimumSize, List children, int columns = 2, float colSpacing = 16.0f, float rowSpacing = 16.0f) + public GridContainer(Rect minimumSize, List children, int columns = 2, float colSpacing = 16.0f, float rowSpacing = 16.0f) : base(minimumSize, children) { Columns = columns; @@ -38,16 +38,13 @@ public class GridContainer : Container public override void Arrange() { - float startX = Position.X; - float startY = Position.Y; - - float currentX = startX; - float currentY = startY; + float currentX = 0.0f; + float currentY = 0.0f; int colIndex = 0; foreach (var child in Children) { - child.Position = new Vector2(currentX, currentY); + child.LocalPosition = new Vector2(currentX, currentY); float childWidth = 0.0f; float childHeight = 0.0f; @@ -60,7 +57,7 @@ public class GridContainer : Container if (colIndex >= Columns) { colIndex = 0; - currentX = startX; + currentX = 0.0f; currentY += childHeight + RowSpacing; } else diff --git a/Voile/Source/UI/Containers/HorizontalContainer.cs b/Voile/Source/UI/Containers/HorizontalContainer.cs index e1934c3..a585089 100644 --- a/Voile/Source/UI/Containers/HorizontalContainer.cs +++ b/Voile/Source/UI/Containers/HorizontalContainer.cs @@ -13,7 +13,7 @@ public class HorizontalContainer : Container /// public float Spacing { get; set; } = 16.0f; - public HorizontalContainer(Rect minimumSize, List children, float spacing = 16.0f) : base(minimumSize, children) + public HorizontalContainer(Rect minimumSize, List children, float spacing = 16.0f) : base(minimumSize, children) { Spacing = spacing; } @@ -25,13 +25,13 @@ public class HorizontalContainer : Container public override void Arrange() { - float currentX = Position.X; + float currentX = 0.0f; for (int i = 0; i < Children.Count; i++) { var child = Children[i]; - var pos = new Vector2(currentX, Position.Y); - child.Position = pos; + var pos = new Vector2(currentX, 0.0f); + child.LocalPosition = pos; currentX += child.Size.Width; diff --git a/Voile/Source/UI/Containers/VerticalContainer.cs b/Voile/Source/UI/Containers/VerticalContainer.cs index 9adbcc7..1ada35a 100644 --- a/Voile/Source/UI/Containers/VerticalContainer.cs +++ b/Voile/Source/UI/Containers/VerticalContainer.cs @@ -13,7 +13,7 @@ public class VerticalContainer : Container /// public float Spacing { get; set; } = 16.0f; - public VerticalContainer(Rect minimumSize, List children, float spacing = 16.0f) : base(minimumSize, children) + public VerticalContainer(Rect minimumSize, List children, float spacing = 16.0f) : base(minimumSize, children) { Spacing = spacing; } @@ -25,13 +25,13 @@ public class VerticalContainer : Container public override void Arrange() { - float currentY = Position.Y; + float currentY = 0.0f; for (int i = 0; i < Children.Count; i++) { var child = Children[i]; - var pos = new Vector2(Position.X, currentY); - child.Position = pos; + var pos = new Vector2(0.0f, currentY); + child.LocalPosition = pos; currentY += child.Size.Height; diff --git a/Voile/Source/UI/IElement.cs b/Voile/Source/UI/IElement.cs index 88884f8..5e1caf7 100644 --- a/Voile/Source/UI/IElement.cs +++ b/Voile/Source/UI/IElement.cs @@ -9,7 +9,7 @@ public interface IElement /// /// This element's position in pixels relative to the viewport top-left edge. /// - public Vector2 Position { get; set; } + public Vector2 GlobalPosition { get; } /// /// The size of this element. /// @@ -21,17 +21,17 @@ public interface IParentableElement /// /// This parentable element's children. /// - public IReadOnlyList Children { get; } + public IReadOnlyList Children { get; } /// /// Add a child element to this element. /// - /// Child . - public void AddChild(IElement child); + /// Child . + public void AddChild(UIElement child); /// /// Remove a child element from this element. /// - /// Child to remove. - public void RemoveChild(IElement child); + /// Child to remove. + public void RemoveChild(UIElement child); } public interface IResizeableElement diff --git a/Voile/Source/UI/UIElement.cs b/Voile/Source/UI/UIElement.cs index a8cc374..6196ce2 100644 --- a/Voile/Source/UI/UIElement.cs +++ b/Voile/Source/UI/UIElement.cs @@ -7,7 +7,9 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme { public bool Visible { get; set; } = true; public bool IgnoreInput { get; set; } = false; - public Vector2 Position { get; set; } = Vector2.Zero; + public Vector2 LocalPosition { get; set; } = Vector2.Zero; + public Vector2 GlobalPosition => _parent?.GlobalPosition + LocalPosition ?? LocalPosition; + public Rect Size { get => _size; @@ -36,6 +38,11 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme public virtual void MarkDirty() => _dirty = true; + public void SetParent(UIElement parent) + { + _parent = parent; + } + public void Update() { if (!_dirty) return; @@ -46,9 +53,9 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme OnUpdate(); - if (_parentRect != Rect.Zero) + if (_parent is not null && _parent.Size != Rect.Zero) { - ApplyAnchor(_parentPosition, _parentRect); + ApplyAnchor(_parent.GlobalPosition, _parent.Size); } } @@ -57,7 +64,7 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme public void DrawSize(RenderSystem renderer) { - renderer.SetTransform(Position, Vector2.Zero); + renderer.SetTransform(GlobalPosition, Vector2.Zero); renderer.DrawRectangleOutline(new Vector2(Size.Width, Size.Height), Color.Red, 2.0f); } @@ -68,9 +75,9 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme /// True if the point is inside the widget; otherwise, false. public bool ContainsPoint(Vector2 point) { - return point.X >= Position.X && point.Y >= Position.Y && - point.X <= Position.X + Size.Width && - point.Y <= Position.Y + Size.Height; + return point.X >= GlobalPosition.X && point.Y >= GlobalPosition.Y && + point.X <= GlobalPosition.X + Size.Width && + point.Y <= GlobalPosition.Y + Size.Height; } /// @@ -78,14 +85,11 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme /// public virtual void ApplyAnchor(Vector2 parentPosition, Rect parentRect) { - _parentPosition = parentPosition; - _parentRect = parentRect; - Position = Anchor.Calculate(parentPosition, parentRect, Size) + new Vector2(AnchorOffset.X, AnchorOffset.Y); + LocalPosition = Anchor.Calculate(parentPosition, parentRect, Size) + new Vector2(AnchorOffset.X, AnchorOffset.Y); } private bool _dirty = true; private Rect _size = Rect.Zero; - private Vector2 _parentPosition = Vector2.Zero; - private Rect _parentRect = Rect.Zero; + private UIElement? _parent; } diff --git a/Voile/Source/UI/UISystem.cs b/Voile/Source/UI/UISystem.cs index bc18fc1..47081e2 100644 --- a/Voile/Source/UI/UISystem.cs +++ b/Voile/Source/UI/UISystem.cs @@ -22,15 +22,15 @@ public class UISystem : IUpdatableSystem, IRenderableSystem _style = style; } - public UISystem(InputSystem inputSystem, ResourceRef