Add debug rectangle size rendering, auto-resize containers to fit all children.
This commit is contained in:
@@ -20,6 +20,7 @@ public class TestGame : Game
|
|||||||
InitializeSystemsDefault();
|
InitializeSystemsDefault();
|
||||||
|
|
||||||
_uiSystem = new UISystem(new ResourceRef<Style>(Guid.Empty));
|
_uiSystem = new UISystem(new ResourceRef<Style>(Guid.Empty));
|
||||||
|
_uiSystem.RenderDebugRects = true;
|
||||||
|
|
||||||
_particleSystem = new ParticleSystem();
|
_particleSystem = new ParticleSystem();
|
||||||
|
|
||||||
|
|||||||
@@ -187,6 +187,17 @@ namespace Voile.Rendering
|
|||||||
}, transformPivot, transformRotation, VoileColorToRaylibColor(color));
|
}, transformPivot, transformRotation, VoileColorToRaylibColor(color));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void DrawRectangleOutline(Vector2 size, Color color, float outlineWidth = 1)
|
||||||
|
{
|
||||||
|
Raylib.DrawRectangleLinesEx(new Rectangle()
|
||||||
|
{
|
||||||
|
X = transformPosition.X,
|
||||||
|
Y = transformPosition.Y,
|
||||||
|
Width = size.X,
|
||||||
|
Height = size.Y
|
||||||
|
}, outlineWidth, VoileColorToRaylibColor(color));
|
||||||
|
}
|
||||||
|
|
||||||
public override void DrawDebugText(string text, int fontSize, Color color)
|
public override void DrawDebugText(string text, int fontSize, Color color)
|
||||||
{
|
{
|
||||||
Raylib.DrawText(text, (int)transformPosition.X, (int)transformPosition.Y, fontSize, VoileColorToRaylibColor(color));
|
Raylib.DrawText(text, (int)transformPosition.X, (int)transformPosition.Y, fontSize, VoileColorToRaylibColor(color));
|
||||||
|
|||||||
@@ -180,6 +180,9 @@ namespace Voile.Rendering
|
|||||||
/// <param name="size">Rectangle size.</param>
|
/// <param name="size">Rectangle size.</param>
|
||||||
/// <param name="color">Fill color.</param>
|
/// <param name="color">Fill color.</param>
|
||||||
public abstract void DrawRectangle(Vector2 size, Color color);
|
public abstract void DrawRectangle(Vector2 size, Color color);
|
||||||
|
|
||||||
|
public abstract void DrawRectangleOutline(Vector2 size, Color color, float outlineWidth = 1.0f);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws a debug text with a default font.
|
/// Draws a debug text with a default font.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -399,6 +399,11 @@ namespace Voile.Rendering
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void DrawRectangleOutline(Vector2 size, Color color, float outlineWidth = 1)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
private Vector2 _windowSize = Vector2.Zero;
|
private Vector2 _windowSize = Vector2.Zero;
|
||||||
private IWindow? _window;
|
private IWindow? _window;
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,40 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using Voile.Rendering;
|
||||||
|
|
||||||
namespace Voile.UI.Containers;
|
namespace Voile.UI.Containers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A base class for all UI containers, used to position and rendering child <see cref="IElement">s.
|
/// A base class for all UI containers, used to position and rendering child <see cref="IElement">s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class Container : IElement, IParentableElement, IUpdatableElement
|
public abstract class Container : IElement, IParentableElement, IUpdatableElement, IResizeableElement, IRenderableElement
|
||||||
{
|
{
|
||||||
public IReadOnlyList<IElement> Children => _children;
|
public IReadOnlyList<IElement> Children => _children;
|
||||||
public Vector2 Position { get; set; }
|
public Vector2 Position { get; set; }
|
||||||
|
public Rect MinimumRect { get; set; } = Rect.Zero;
|
||||||
public Rect Size { get; set; } = Rect.Zero;
|
public Rect Size { get; set; } = Rect.Zero;
|
||||||
|
public bool Visible { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||||
|
|
||||||
public Container()
|
public Container()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Container(List<IElement> children)
|
public Container(Rect minimumSize)
|
||||||
{
|
{
|
||||||
|
MinimumRect = minimumSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Container(Rect minimumSize, List<IElement> children)
|
||||||
|
{
|
||||||
|
MinimumRect = minimumSize;
|
||||||
_children = children;
|
_children = children;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
Arrange();
|
Arrange();
|
||||||
|
CalculateMinimumSize();
|
||||||
|
|
||||||
foreach (var child in _children)
|
foreach (var child in _children)
|
||||||
{
|
{
|
||||||
if (child is not IUpdatableElement updatable) continue;
|
if (child is not IUpdatableElement updatable) continue;
|
||||||
@@ -32,11 +43,59 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
|
|||||||
}
|
}
|
||||||
public abstract void Arrange();
|
public abstract void Arrange();
|
||||||
|
|
||||||
|
public void CalculateMinimumSize()
|
||||||
|
{
|
||||||
|
if (Children.Count == 0)
|
||||||
|
{
|
||||||
|
Size = MinimumRect;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float minX = float.MaxValue;
|
||||||
|
float minY = float.MaxValue;
|
||||||
|
float maxX = float.MinValue;
|
||||||
|
float maxY = float.MinValue;
|
||||||
|
|
||||||
|
foreach (var child in Children)
|
||||||
|
{
|
||||||
|
var pos = child.Position;
|
||||||
|
var size = child.Size;
|
||||||
|
|
||||||
|
minX = MathF.Min(minX, pos.X);
|
||||||
|
minY = MathF.Min(minY, pos.Y);
|
||||||
|
maxX = MathF.Max(maxX, pos.X + size.Width);
|
||||||
|
maxY = MathF.Max(maxY, pos.Y + size.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optionally apply padding
|
||||||
|
float padding = 0f; // or make this configurable
|
||||||
|
|
||||||
|
Size = new Rect(
|
||||||
|
maxX - minX + padding * 2,
|
||||||
|
maxY - minY + padding * 2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public void AddChild(IElement child)
|
public void AddChild(IElement child)
|
||||||
{
|
{
|
||||||
_children.Add(child);
|
_children.Add(child);
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Render(RenderSystem renderer, Style style)
|
||||||
|
{
|
||||||
|
foreach (var child in Children)
|
||||||
|
{
|
||||||
|
if (child is not IRenderableElement renderable) continue;
|
||||||
|
renderable.Render(renderer, style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawSize(RenderSystem renderer)
|
||||||
|
{
|
||||||
|
renderer.SetTransform(Position, Vector2.Zero);
|
||||||
|
renderer.DrawRectangleOutline(new Vector2(Size.Width, Size.Height), Color.Red, 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
private List<IElement> _children = new();
|
private List<IElement> _children = new();
|
||||||
}
|
}
|
||||||
@@ -3,15 +3,14 @@ using Voile.Rendering;
|
|||||||
|
|
||||||
namespace Voile.UI.Containers;
|
namespace Voile.UI.Containers;
|
||||||
|
|
||||||
public class GridContainer : Container, IRenderableElement
|
public class GridContainer : Container
|
||||||
{
|
{
|
||||||
public int Columns { get; set; } = 2;
|
public int Columns { get; set; } = 2;
|
||||||
public float ColumnSpacing { get; set; } = 16.0f;
|
public float ColumnSpacing { get; set; } = 16.0f;
|
||||||
public float RowSpacing { get; set; } = 16.0f;
|
public float RowSpacing { get; set; } = 16.0f;
|
||||||
public bool Visible { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
||||||
|
|
||||||
public GridContainer(List<IElement> children, int columns = 2, float colSpacing = 16.0f, float rowSpacing = 16.0f)
|
public GridContainer(Rect minimumSize, List<IElement> children, int columns = 2, float colSpacing = 16.0f, float rowSpacing = 16.0f)
|
||||||
: base(children)
|
: base(minimumSize, children)
|
||||||
{
|
{
|
||||||
Columns = columns;
|
Columns = columns;
|
||||||
ColumnSpacing = colSpacing;
|
ColumnSpacing = colSpacing;
|
||||||
@@ -58,13 +57,4 @@ public class GridContainer : Container, IRenderableElement
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render(RenderSystem renderer, Style style)
|
|
||||||
{
|
|
||||||
foreach (var child in Children)
|
|
||||||
{
|
|
||||||
if (child is not IRenderableElement renderable) continue;
|
|
||||||
renderable.Render(renderer, style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -3,12 +3,11 @@ using Voile.Rendering;
|
|||||||
|
|
||||||
namespace Voile.UI.Containers;
|
namespace Voile.UI.Containers;
|
||||||
|
|
||||||
public class HorizontalContainer : Container, IRenderableElement
|
public class HorizontalContainer : Container
|
||||||
{
|
{
|
||||||
public float Spacing { get; set; } = 16.0f;
|
public float Spacing { get; set; } = 16.0f;
|
||||||
public bool Visible { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
||||||
|
|
||||||
public HorizontalContainer(List<IElement> children, float spacing = 16.0f) : base(children)
|
public HorizontalContainer(Rect minimumSize, List<IElement> children, float spacing = 16.0f) : base(minimumSize, children)
|
||||||
{
|
{
|
||||||
Spacing = spacing;
|
Spacing = spacing;
|
||||||
}
|
}
|
||||||
@@ -36,13 +35,4 @@ public class HorizontalContainer : Container, IRenderableElement
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render(RenderSystem renderer, Style style)
|
|
||||||
{
|
|
||||||
foreach (var child in Children)
|
|
||||||
{
|
|
||||||
if (child is not IRenderableElement renderable) continue;
|
|
||||||
renderable.Render(renderer, style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -3,12 +3,11 @@ using Voile.Rendering;
|
|||||||
|
|
||||||
namespace Voile.UI.Containers;
|
namespace Voile.UI.Containers;
|
||||||
|
|
||||||
public class VerticalContainer : Container, IRenderableElement
|
public class VerticalContainer : Container
|
||||||
{
|
{
|
||||||
public float Spacing { get; set; } = 16.0f;
|
public float Spacing { get; set; } = 16.0f;
|
||||||
public bool Visible { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
||||||
|
|
||||||
public VerticalContainer(List<IElement> children, float spacing = 16.0f) : base(children)
|
public VerticalContainer(Rect minimumSize, List<IElement> children, float spacing = 16.0f) : base(minimumSize, children)
|
||||||
{
|
{
|
||||||
Spacing = spacing;
|
Spacing = spacing;
|
||||||
}
|
}
|
||||||
@@ -36,13 +35,4 @@ public class VerticalContainer : Container, IRenderableElement
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render(RenderSystem renderer, Style style)
|
|
||||||
{
|
|
||||||
foreach (var child in Children)
|
|
||||||
{
|
|
||||||
if (child is not IRenderableElement renderable) continue;
|
|
||||||
renderable.Render(renderer, style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -33,6 +33,7 @@ public interface IRenderableElement
|
|||||||
{
|
{
|
||||||
public bool Visible { get; set; }
|
public bool Visible { get; set; }
|
||||||
public void Render(RenderSystem renderer, Style style);
|
public void Render(RenderSystem renderer, Style style);
|
||||||
|
public void DrawSize(RenderSystem renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IInputElement
|
public interface IInputElement
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Numerics;
|
||||||
using Voile.Rendering;
|
using Voile.Rendering;
|
||||||
using Voile.UI.Containers;
|
using Voile.UI.Containers;
|
||||||
|
|
||||||
@@ -7,6 +8,8 @@ public class UISystem : IUpdatableSystem, IRenderableSystem
|
|||||||
{
|
{
|
||||||
public IReadOnlyList<IElement> Elements => _elements;
|
public IReadOnlyList<IElement> Elements => _elements;
|
||||||
|
|
||||||
|
public bool RenderDebugRects { get; set; }
|
||||||
|
|
||||||
public UISystem(ResourceRef<Style> style)
|
public UISystem(ResourceRef<Style> style)
|
||||||
{
|
{
|
||||||
_style = style;
|
_style = style;
|
||||||
@@ -37,6 +40,20 @@ public class UISystem : IUpdatableSystem, IRenderableSystem
|
|||||||
if (element is IRenderableElement renderable)
|
if (element is IRenderableElement renderable)
|
||||||
{
|
{
|
||||||
renderable.Render(renderer, _style.Value);
|
renderable.Render(renderer, _style.Value);
|
||||||
|
|
||||||
|
if (!RenderDebugRects) return;
|
||||||
|
renderable.DrawSize(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element is IParentableElement parentable)
|
||||||
|
{
|
||||||
|
foreach (var child in parentable.Children)
|
||||||
|
{
|
||||||
|
if (child is not IRenderableElement renderableChild) continue;
|
||||||
|
|
||||||
|
if (!RenderDebugRects) return;
|
||||||
|
renderableChild.DrawSize(renderer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public abstract class Widget : IElement, IRenderableElement, IInputElement, IRes
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="renderer"></param>
|
/// <param name="renderer"></param>
|
||||||
public abstract void Render(RenderSystem renderer, Style style);
|
public abstract void Render(RenderSystem renderer, Style style);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when this widget receives input.
|
/// Called when this widget receives input.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -45,4 +46,10 @@ public abstract class Widget : IElement, IRenderableElement, IInputElement, IRes
|
|||||||
Size = MinimumRect;
|
Size = MinimumRect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DrawSize(RenderSystem renderer)
|
||||||
|
{
|
||||||
|
renderer.SetTransform(Position, Vector2.Zero);
|
||||||
|
renderer.DrawRectangleOutline(new Vector2(Size.Width, Size.Height), Color.Red, 2.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
<PackageReference Include="SoLoud.NET" Version="2020.2.7.1" />
|
<PackageReference Include="SoLoud.NET" Version="2020.2.7.1" />
|
||||||
<PackageReference Include="Tommy" Version="3.1.2" />
|
<PackageReference Include="Tommy" Version="3.1.2" />
|
||||||
<PackageReference Include="ImGui.NET" Version="1.89.4" />
|
<PackageReference Include="ImGui.NET" Version="1.89.4" />
|
||||||
<PackageReference Include="Raylib-cs" Version="6.1.1" />
|
<PackageReference Include="Raylib-cs" Version="7.0.1" />
|
||||||
<PackageReference Include="SharpFont" Version="4.0.1" />
|
<PackageReference Include="SharpFont" Version="4.0.1" />
|
||||||
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta19" />
|
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta19" />
|
||||||
<PackageReference Include="StbImageSharp" Version="2.27.13" />
|
<PackageReference Include="StbImageSharp" Version="2.27.13" />
|
||||||
|
|||||||
Reference in New Issue
Block a user