diff --git a/TestGame/TestGame.cs b/TestGame/TestGame.cs index fa70522..0cc5832 100644 --- a/TestGame/TestGame.cs +++ b/TestGame/TestGame.cs @@ -56,7 +56,8 @@ public class TestGame : Game Input.AddInputMapping("reload", new IInputAction[] { new KeyInputAction(KeyboardKey.R) }); _emitterId = _particleSystem.CreateEmitter(Renderer.WindowSize / 2, _fireEffect); - _fillContainer.AddChild(_container); + _fillContainer.AddChild(_marginContainer); + _marginContainer.AddChild(_container); _uiSystem.AddElement(_fillContainer); } @@ -129,21 +130,20 @@ public class TestGame : Game private FlexContainer _container = new(minimumSize: new Rect(64.0f, 64.0f), new()) { - ConfineToContents = true, Anchor = Anchor.Center, - Size = new Rect(500, 300), Direction = FlexDirection.Column, Justify = JustifyContent.Start, Align = AlignItems.Center, Wrap = true, - Gap = 10f + Gap = 8.0f }; private FillContainer _fillContainer = new(); + private MarginContainer _marginContainer = new(new Margin(32.0f)) + { + }; // private HorizontalContainer _container = new(new Rect(128.0f, 64.0f), new(), 16) // { // ConfineToContents = true, - // Anchor = Anchor.CenterRight, - // 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 c9112ca..b5db935 100644 --- a/Voile/Source/UI/Containers/Container.cs +++ b/Voile/Source/UI/Containers/Container.cs @@ -60,6 +60,18 @@ public abstract class Container : UIElement, IParentableElement } } + public override void MarkDirty() + { + base.MarkDirty(); + + foreach (var child in _children) + { + if (child is not IUpdatableElement updatable) continue; + + updatable.MarkDirty(); + } + } + /// /// Called when this has to rearrange its children. /// diff --git a/Voile/Source/UI/Containers/FillContainer.cs b/Voile/Source/UI/Containers/FillContainer.cs index 15b0897..1a08b85 100644 --- a/Voile/Source/UI/Containers/FillContainer.cs +++ b/Voile/Source/UI/Containers/FillContainer.cs @@ -51,9 +51,6 @@ public class FillContainer : Container protected override void OnUpdate() { base.OnUpdate(); - - if (Size == _lastParentSize) return; - Size = _lastParentSize; } diff --git a/Voile/Source/UI/Containers/MarginContainer.cs b/Voile/Source/UI/Containers/MarginContainer.cs new file mode 100644 index 0000000..bf3d586 --- /dev/null +++ b/Voile/Source/UI/Containers/MarginContainer.cs @@ -0,0 +1,78 @@ +using System.Numerics; + +namespace Voile.UI.Containers; + +/// +/// Represents the margin offsets applied around an element. +/// +public struct Margin +{ + public float Left; + public float Right; + public float Top; + public float Bottom; + + public Margin(float uniform) + { + Left = Right = Top = Bottom = uniform; + } + + public Margin(float horizontal, float vertical) + { + Left = Right = horizontal; + Top = Bottom = vertical; + } + + public Margin(float left, float right, float top, float bottom) + { + Left = left; + Right = right; + Top = top; + Bottom = bottom; + } + + public static Margin Zero => new Margin(0); +} + +public class MarginContainer : Container +{ + /// + /// The margin to apply around the contents of this container. + /// + public Margin Margin { get; set; } + + /// + /// Specifies if this will fill to parent size. + /// + public bool Fill { get; set; } = true; + + public MarginContainer() : this(new Margin()) { } + + public MarginContainer(Margin margin) + { + Margin = margin; + } + + protected override void OnUpdate() + { + base.OnUpdate(); + if (Parent == null) return; + + Size = Parent.Size; + } + + public override void Arrange() + { + foreach (var child in Children) + { + var newPosition = new Vector2(Margin.Left, Margin.Top); + var newSize = new Rect( + Size.Width - Margin.Left - Margin.Right, + Size.Height - Margin.Top - Margin.Bottom + ); + + child.Size = newSize; + child.LocalPosition = newPosition; + } + } +} \ No newline at end of file diff --git a/Voile/Source/UI/UIElement.cs b/Voile/Source/UI/UIElement.cs index 4a2a894..0b7fc09 100644 --- a/Voile/Source/UI/UIElement.cs +++ b/Voile/Source/UI/UIElement.cs @@ -23,8 +23,6 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme get => _size; set { - _size = value; - if (value.Width < MinimumSize.Width) { _size.Width = MinimumSize.Width; @@ -35,7 +33,12 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme _size.Height = MinimumSize.Height; } - MarkDirty(); + if (_size != value) + { + MarkDirty(); + } + + _size = value; } } public Vector2 AnchorOffset { get; set; } = Vector2.Zero; @@ -44,7 +47,15 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme public abstract Rect MinimumSize { get; } public bool Dirty => _dirty; - public virtual void MarkDirty() => _dirty = true; + public virtual void MarkDirty() + { + if (Parent != null && !Parent.Dirty) + { + Parent.MarkDirty(); + } + + _dirty = true; + } /// /// Sets a parent element for this .