WIP: dirty flag for UI.
This commit is contained in:
@@ -8,41 +8,65 @@ namespace Voile.UI.Containers;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class Container : IElement, IParentableElement, IUpdatableElement, IResizeableElement, IRenderableElement
|
public abstract class Container : IElement, IParentableElement, IUpdatableElement, IResizeableElement, IRenderableElement
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
public IReadOnlyList<IElement> Children => _children;
|
public IReadOnlyList<IElement> Children => _children;
|
||||||
|
/// <inheritdoc />
|
||||||
public Vector2 Position { get; set; }
|
public Vector2 Position { get; set; }
|
||||||
|
/// <inheritdoc />
|
||||||
public Rect MinimumRect { get; set; } = Rect.Zero;
|
public Rect MinimumRect { get; set; } = Rect.Zero;
|
||||||
|
/// <inheritdoc />
|
||||||
public Rect Size { get; set; } = Rect.Zero;
|
public Rect Size { get; set; } = Rect.Zero;
|
||||||
|
/// <inheritdoc />
|
||||||
public bool Visible { get; set; } = true;
|
public bool Visible { get; set; } = true;
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool Dirty => _isDirty;
|
||||||
|
|
||||||
public Container()
|
public Container()
|
||||||
{
|
{
|
||||||
|
MarkDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Container(Rect minimumSize)
|
public Container(Rect minimumSize)
|
||||||
{
|
{
|
||||||
MinimumRect = minimumSize;
|
MinimumRect = minimumSize;
|
||||||
|
|
||||||
|
MarkDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Container(Rect minimumSize, List<IElement> children)
|
public Container(Rect minimumSize, List<IElement> children)
|
||||||
{
|
{
|
||||||
MinimumRect = minimumSize;
|
MinimumRect = minimumSize;
|
||||||
_children = children;
|
_children = children;
|
||||||
|
|
||||||
|
MarkDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
Arrange();
|
if (!_isDirty) return;
|
||||||
CalculateMinimumSize();
|
_isDirty = false;
|
||||||
|
|
||||||
|
|
||||||
foreach (var child in _children)
|
foreach (var child in _children)
|
||||||
{
|
{
|
||||||
if (child is not IUpdatableElement updatable) continue;
|
if (child is not IUpdatableElement updatable) continue;
|
||||||
updatable.Update();
|
updatable.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Arrange();
|
||||||
|
CalculateMinimumSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void MarkDirty() => _isDirty = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when this <see cref="Container"/> has to rearrange its children.
|
||||||
|
/// </summary>
|
||||||
public abstract void Arrange();
|
public abstract void Arrange();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recalculates a minimum size for this <see cref="Container"/>.
|
||||||
|
/// </summary>
|
||||||
public void CalculateMinimumSize()
|
public void CalculateMinimumSize()
|
||||||
{
|
{
|
||||||
if (Children.Count == 0)
|
if (Children.Count == 0)
|
||||||
@@ -81,12 +105,16 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
|
|||||||
public void AddChild(IElement child)
|
public void AddChild(IElement child)
|
||||||
{
|
{
|
||||||
_children.Add(child);
|
_children.Add(child);
|
||||||
|
|
||||||
|
MarkDirty();
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveChild(IElement child)
|
public void RemoveChild(IElement child)
|
||||||
{
|
{
|
||||||
_children.Remove(child);
|
_children.Remove(child);
|
||||||
|
|
||||||
|
MarkDirty();
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,4 +134,5 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<IElement> _children = new();
|
private List<IElement> _children = new();
|
||||||
|
private bool _isDirty;
|
||||||
}
|
}
|
||||||
@@ -6,14 +6,31 @@ namespace Voile.UI;
|
|||||||
|
|
||||||
public interface IElement
|
public interface IElement
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This element's position in pixels relative to the viewport top-left edge.
|
||||||
|
/// </summary>
|
||||||
public Vector2 Position { get; set; }
|
public Vector2 Position { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The size of this element.
|
||||||
|
/// </summary>
|
||||||
public Rect Size { get; set; }
|
public Rect Size { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IParentableElement
|
public interface IParentableElement
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This parentable element's children.
|
||||||
|
/// </summary>
|
||||||
public IReadOnlyList<IElement> Children { get; }
|
public IReadOnlyList<IElement> Children { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Add a child element to this element.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="child">Child <see cref="IElement"/>.</param>
|
||||||
public void AddChild(IElement child);
|
public void AddChild(IElement child);
|
||||||
|
/// <summary>
|
||||||
|
/// Remove a child element from this element.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="child">Child <see cref="IElement"/> to remove.</param>
|
||||||
public void RemoveChild(IElement child);
|
public void RemoveChild(IElement child);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,18 +44,48 @@ public interface IResizeableElement
|
|||||||
|
|
||||||
public interface IUpdatableElement
|
public interface IUpdatableElement
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies if this element's properties have changed, making it necessary to update it.
|
||||||
|
/// </summary>
|
||||||
|
public bool Dirty { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Update this element.
|
||||||
|
/// </summary>
|
||||||
void Update();
|
void Update();
|
||||||
|
/// <summary>
|
||||||
|
/// Marks this element as changed, requiring an update.
|
||||||
|
/// </summary>
|
||||||
|
void MarkDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IRenderableElement
|
public interface IRenderableElement
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies if this element should be drawn.
|
||||||
|
/// </summary>
|
||||||
public bool Visible { get; set; }
|
public bool Visible { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Render this element.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="renderer">Renderer to call draw operations on.</param>
|
||||||
|
/// <param name="style">A style to use to draw this element.</param>
|
||||||
public void Render(RenderSystem renderer, Style style);
|
public void Render(RenderSystem renderer, Style style);
|
||||||
|
/// <summary>
|
||||||
|
/// Draws this element's size bounds.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="renderer">Renderer to use.</param>
|
||||||
public void DrawSize(RenderSystem renderer);
|
public void DrawSize(RenderSystem renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IInputElement
|
public interface IInputElement
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies if this element should ignore inputs.
|
||||||
|
/// </summary>
|
||||||
public bool IgnoreInput { get; set; }
|
public bool IgnoreInput { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Send an input action to this element.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">Input action to send.</param>
|
||||||
void Input(IInputAction action);
|
void Input(IInputAction action);
|
||||||
}
|
}
|
||||||
@@ -22,11 +22,14 @@ public abstract class Widget : IElement, IRenderableElement, IInputElement, IRes
|
|||||||
public Widget(Vector2 position)
|
public Widget(Vector2 position)
|
||||||
{
|
{
|
||||||
Position = position;
|
Position = position;
|
||||||
|
Size = MinimumRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// </inheritdoc>
|
/// </inheritdoc>
|
||||||
public abstract Rect MinimumRect { get; }
|
public abstract Rect MinimumRect { get; }
|
||||||
|
|
||||||
|
public bool Dirty => _isDirty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when its time to draw this widget.
|
/// Called when its time to draw this widget.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -41,15 +44,22 @@ public abstract class Widget : IElement, IRenderableElement, IInputElement, IRes
|
|||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
|
if (!_isDirty) return;
|
||||||
|
_isDirty = false;
|
||||||
|
|
||||||
if (Size == Rect.Zero)
|
if (Size == Rect.Zero)
|
||||||
{
|
{
|
||||||
Size = MinimumRect;
|
Size = MinimumRect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void MarkDirty() => _isDirty = true;
|
||||||
|
|
||||||
public void DrawSize(RenderSystem renderer)
|
public void DrawSize(RenderSystem renderer)
|
||||||
{
|
{
|
||||||
renderer.SetTransform(Position, Vector2.Zero);
|
renderer.SetTransform(Position, Vector2.Zero);
|
||||||
renderer.DrawRectangleOutline(new Vector2(Size.Width, Size.Height), Color.Red, 2.0f);
|
renderer.DrawRectangleOutline(new Vector2(Size.Width, Size.Height), Color.Red, 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _isDirty = true;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user