Unify Containers and Widgets by creating a base UIElement, add more anchor types, make anchor calculations an extension of Anchor.
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Voile.UI;
|
namespace Voile.UI;
|
||||||
|
|
||||||
public enum Anchor
|
public enum Anchor
|
||||||
@@ -5,11 +7,35 @@ public enum Anchor
|
|||||||
TopLeft,
|
TopLeft,
|
||||||
TopCenter,
|
TopCenter,
|
||||||
TopRight,
|
TopRight,
|
||||||
Left,
|
CenterLeft,
|
||||||
Center,
|
Center,
|
||||||
Right,
|
CenterRight,
|
||||||
BottomLeft,
|
BottomLeft,
|
||||||
BottomCenter,
|
BottomCenter,
|
||||||
BottomRight,
|
BottomRight,
|
||||||
Fill
|
Fill
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class AnchorExtensions
|
||||||
|
{
|
||||||
|
public static Vector2 Calculate(this Anchor anchor, Vector2 parentPosition, Rect parentRect, Rect elementRect)
|
||||||
|
{
|
||||||
|
var size = new Vector2(elementRect.Width, elementRect.Height);
|
||||||
|
var parentSize = new Vector2(parentRect.Width, parentRect.Height);
|
||||||
|
|
||||||
|
return anchor switch
|
||||||
|
{
|
||||||
|
Anchor.TopLeft => Vector2.Zero,
|
||||||
|
Anchor.TopCenter => new Vector2((parentSize.X - size.X) / 2, 0),
|
||||||
|
Anchor.TopRight => new Vector2(parentSize.X - size.X, 0),
|
||||||
|
Anchor.CenterLeft => new Vector2(0, (parentSize.Y - size.Y) / 2),
|
||||||
|
Anchor.Center => (parentSize - size) / 2,
|
||||||
|
Anchor.CenterRight => new Vector2(parentSize.X - size.X, (parentSize.Y - size.Y) / 2),
|
||||||
|
Anchor.BottomLeft => new Vector2(0, parentSize.Y - size.Y),
|
||||||
|
Anchor.BottomCenter => new Vector2((parentSize.X - size.X) / 2, parentSize.Y - size.Y),
|
||||||
|
Anchor.BottomRight => parentSize - size,
|
||||||
|
_ => Vector2.Zero
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,46 +7,17 @@ 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, IResizeableElement, IRenderableElement, IAnchorableElement
|
public abstract class Container : UIElement, IParentableElement
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IReadOnlyList<IElement> Children => _children;
|
public IReadOnlyList<IElement> Children => _children;
|
||||||
/// <inheritdoc />
|
|
||||||
public Vector2 Position { get; set; }
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Rect MinimumRect { get; set; } = Rect.Zero;
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Rect Size
|
|
||||||
{
|
|
||||||
get => _size;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_size = value;
|
|
||||||
|
|
||||||
if (value.Width < MinimumRect.Width)
|
|
||||||
{
|
|
||||||
_size.Width = MinimumRect.Width;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.Height < MinimumRect.Height)
|
|
||||||
{
|
|
||||||
_size.Height = MinimumRect.Height;
|
|
||||||
}
|
|
||||||
|
|
||||||
MarkDirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <inheritdoc />
|
|
||||||
public bool Visible { get; set; } = true;
|
|
||||||
/// <inheritdoc />
|
|
||||||
public bool Dirty => _isDirty;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies if this <see cref="Container"/>'s minimum size will be confined to contents.
|
/// Specifies if this <see cref="Container"/>'s minimum size will be confined to contents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ConfineToContents { get; set; } = false;
|
public bool ConfineToContents { get; set; } = false;
|
||||||
public Anchor Anchor { get; set; }
|
|
||||||
public Vector2 AnchorOffset { get; set; }
|
public override Rect MinimumSize => _minimumSize;
|
||||||
|
|
||||||
public Container()
|
public Container()
|
||||||
{
|
{
|
||||||
@@ -55,28 +26,26 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
|
|||||||
|
|
||||||
public Container(Rect minimumSize)
|
public Container(Rect minimumSize)
|
||||||
{
|
{
|
||||||
MinimumRect = minimumSize;
|
_minimumSize = minimumSize;
|
||||||
|
|
||||||
MarkDirty();
|
MarkDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Container(Rect minimumSize, List<IElement> children)
|
public Container(Rect minimumSize, List<IElement> children)
|
||||||
{
|
{
|
||||||
MinimumRect = minimumSize;
|
_minimumSize = minimumSize;
|
||||||
_children = children;
|
_children = children;
|
||||||
|
|
||||||
MarkDirty();
|
MarkDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
protected override void OnUpdate()
|
||||||
{
|
{
|
||||||
if (!_isDirty) return;
|
|
||||||
_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.MarkDirty();
|
||||||
updatable.Update();
|
updatable.Update();
|
||||||
|
|
||||||
if (child is IAnchorableElement anchorable)
|
if (child is IAnchorableElement anchorable)
|
||||||
@@ -93,8 +62,6 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MarkDirty() => _isDirty = true;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when this <see cref="Container"/> has to rearrange its children.
|
/// Called when this <see cref="Container"/> has to rearrange its children.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -127,14 +94,14 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
|
|||||||
float occupiedWidth = (maxX - minX) + padding * 2;
|
float occupiedWidth = (maxX - minX) + padding * 2;
|
||||||
float occupiedHeight = (maxY - minY) + padding * 2;
|
float occupiedHeight = (maxY - minY) + padding * 2;
|
||||||
|
|
||||||
float finalWidth = MathF.Max(occupiedWidth, MinimumRect.Width);
|
float finalWidth = MathF.Max(occupiedWidth, _minimumSize.Width);
|
||||||
float finalHeight = MathF.Max(occupiedHeight, MinimumRect.Height);
|
float finalHeight = MathF.Max(occupiedHeight, _minimumSize.Height);
|
||||||
|
|
||||||
MinimumRect = new Rect(finalWidth, finalHeight);
|
Size = new Rect(finalWidth, finalHeight);
|
||||||
|
|
||||||
if (MinimumRect > _size)
|
if (_minimumSize > Size)
|
||||||
{
|
{
|
||||||
_size = MinimumRect;
|
Size = _minimumSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +121,7 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
|
|||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render(RenderSystem renderer, Style style)
|
public override void Render(RenderSystem renderer, Style style)
|
||||||
{
|
{
|
||||||
foreach (var child in Children)
|
foreach (var child in Children)
|
||||||
{
|
{
|
||||||
@@ -163,45 +130,6 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawSize(RenderSystem renderer)
|
|
||||||
{
|
|
||||||
renderer.SetTransform(Position, Vector2.Zero);
|
|
||||||
renderer.DrawRectangleOutline(new Vector2(Size.Width, Size.Height), Color.Red, 2.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ApplyAnchor(Vector2 parentPosition, Rect parentRect)
|
|
||||||
{
|
|
||||||
var absoluteOffset = AnchorOffset * new Vector2(Size.Width, Size.Height);
|
|
||||||
|
|
||||||
switch (Anchor)
|
|
||||||
{
|
|
||||||
case Anchor.TopLeft:
|
|
||||||
Position = parentPosition - AnchorOffset;
|
|
||||||
break;
|
|
||||||
case Anchor.TopCenter:
|
|
||||||
var topCenterX = parentRect.Width / 2;
|
|
||||||
var topCenterY = parentPosition.Y;
|
|
||||||
|
|
||||||
Position = new Vector2(parentPosition.X + topCenterX, topCenterY) - absoluteOffset;
|
|
||||||
break;
|
|
||||||
case Anchor.TopRight:
|
|
||||||
Position = new Vector2(parentPosition.X + parentRect.Width, parentPosition.Y) - absoluteOffset;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Anchor.Fill:
|
|
||||||
Position = parentPosition;
|
|
||||||
Size = parentRect;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotImplementedException("This anchor type is not implemented!");
|
|
||||||
}
|
|
||||||
|
|
||||||
MarkDirty();
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<IElement> _children = new();
|
private List<IElement> _children = new();
|
||||||
private bool _isDirty;
|
private Rect _minimumSize = Rect.Zero;
|
||||||
private Rect _size = Rect.Zero;
|
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ public class FlexContainer : Container
|
|||||||
private Vector2 GetChildSize(IElement child)
|
private Vector2 GetChildSize(IElement child)
|
||||||
{
|
{
|
||||||
if (child is IResizeableElement resizeable)
|
if (child is IResizeableElement resizeable)
|
||||||
return new Vector2(resizeable.MinimumRect.Width, resizeable.MinimumRect.Height);
|
return new Vector2(resizeable.MinimumSize.Width, resizeable.MinimumSize.Height);
|
||||||
return new Vector2(child.Size.Width, child.Size.Height);
|
return new Vector2(child.Size.Width, child.Size.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public interface IResizeableElement
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a minimum rectangle size for this element.
|
/// Get a minimum rectangle size for this element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract Rect MinimumRect { get; }
|
public abstract Rect MinimumSize { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IUpdatableElement
|
public interface IUpdatableElement
|
||||||
|
|||||||
91
Voile/Source/UI/UIElement.cs
Normal file
91
Voile/Source/UI/UIElement.cs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Voile.Rendering;
|
||||||
|
|
||||||
|
namespace Voile.UI;
|
||||||
|
|
||||||
|
public abstract class UIElement : IElement, IRenderableElement, IResizeableElement, IUpdatableElement, IAnchorableElement
|
||||||
|
{
|
||||||
|
public bool Visible { get; set; } = true;
|
||||||
|
public bool IgnoreInput { get; set; } = false;
|
||||||
|
public Vector2 Position { get; set; } = Vector2.Zero;
|
||||||
|
public Rect Size
|
||||||
|
{
|
||||||
|
get => _size;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_size = value;
|
||||||
|
|
||||||
|
if (value.Width < MinimumSize.Width)
|
||||||
|
{
|
||||||
|
_size.Width = MinimumSize.Width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.Height < MinimumSize.Height)
|
||||||
|
{
|
||||||
|
_size.Height = MinimumSize.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Vector2 AnchorOffset { get; set; } = Vector2.Zero;
|
||||||
|
public Anchor Anchor { get; set; } = Anchor.TopLeft;
|
||||||
|
|
||||||
|
public abstract Rect MinimumSize { get; }
|
||||||
|
public bool Dirty => _dirty;
|
||||||
|
|
||||||
|
public virtual void MarkDirty() => _dirty = true;
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (!_dirty) return;
|
||||||
|
_dirty = false;
|
||||||
|
|
||||||
|
if (Size == Rect.Zero)
|
||||||
|
Size = MinimumSize;
|
||||||
|
|
||||||
|
OnUpdate();
|
||||||
|
|
||||||
|
if (_parentRect != Rect.Zero)
|
||||||
|
{
|
||||||
|
ApplyAnchor(_parentPosition, _parentRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Render(RenderSystem renderer, Style style);
|
||||||
|
protected abstract void OnUpdate();
|
||||||
|
|
||||||
|
public void DrawSize(RenderSystem renderer)
|
||||||
|
{
|
||||||
|
renderer.SetTransform(Position, Vector2.Zero);
|
||||||
|
renderer.DrawRectangleOutline(new Vector2(Size.Width, Size.Height), Color.Red, 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if this <see cref="UIElement"/> contains a point within its confines.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pointPosition">A global position of the point.</param>
|
||||||
|
/// <returns>True if the point is inside the widget; otherwise, false.</returns>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies this <see cref="UIElement"/> anchor.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void ApplyAnchor(Vector2 parentPosition, Rect parentRect)
|
||||||
|
{
|
||||||
|
_parentPosition = parentPosition;
|
||||||
|
_parentRect = parentRect;
|
||||||
|
Position = 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;
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ public enum ButtonState
|
|||||||
public class Button : Widget
|
public class Button : Widget
|
||||||
{
|
{
|
||||||
public string Label { get; set; } = "Button";
|
public string Label { get; set; } = "Button";
|
||||||
public override Rect MinimumRect => new Rect(Width: 128.0f, Height: 64.0f);
|
public override Rect MinimumSize => new Rect(Width: 128.0f, Height: 64.0f);
|
||||||
|
|
||||||
public Button(string label, Action pressedAction)
|
public Button(string label, Action pressedAction)
|
||||||
{
|
{
|
||||||
@@ -30,7 +30,7 @@ public class Button : Widget
|
|||||||
{
|
{
|
||||||
// TODO: use a button color from style.
|
// TODO: use a button color from style.
|
||||||
renderer.SetTransform(Position, Vector2.Zero);
|
renderer.SetTransform(Position, Vector2.Zero);
|
||||||
renderer.DrawRectangle(new Vector2(MinimumRect.Width, MinimumRect.Height), new Color(0.25f, 0.25f, 0.25f));
|
renderer.DrawRectangle(new Vector2(MinimumSize.Width, MinimumSize.Height), new Color(0.25f, 0.25f, 0.25f));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnInput(UIInputContext action)
|
protected override void OnInput(UIInputContext action)
|
||||||
@@ -38,5 +38,10 @@ public class Button : Widget
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnUpdate()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
private Action _pressedAction;
|
private Action _pressedAction;
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@ namespace Voile.UI.Widgets;
|
|||||||
|
|
||||||
public class Label : Widget
|
public class Label : Widget
|
||||||
{
|
{
|
||||||
public override Rect MinimumRect => throw new NotImplementedException();
|
public override Rect MinimumSize => throw new NotImplementedException();
|
||||||
|
|
||||||
public string Text { get; set; } = "Hello World!";
|
public string Text { get; set; } = "Hello World!";
|
||||||
|
|
||||||
@@ -34,5 +34,10 @@ public class Label : Widget
|
|||||||
renderer.DrawText(_fontOverride, Text, Color.White);
|
renderer.DrawText(_fontOverride, Text, Color.White);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnUpdate()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
private ResourceRef<Font> _fontOverride = ResourceRef<Font>.Empty();
|
private ResourceRef<Font> _fontOverride = ResourceRef<Font>.Empty();
|
||||||
}
|
}
|
||||||
@@ -6,11 +6,11 @@ namespace Voile.UI.Widgets;
|
|||||||
|
|
||||||
public class RectangleWidget : Widget
|
public class RectangleWidget : Widget
|
||||||
{
|
{
|
||||||
public override Rect MinimumRect { get; }
|
public override Rect MinimumSize { get; }
|
||||||
public Color Color { get; set; } = Color.White;
|
public Color Color { get; set; } = Color.White;
|
||||||
public RectangleWidget(Rect minimumRect, Color color) : base()
|
public RectangleWidget(Rect minimumRect, Color color) : base()
|
||||||
{
|
{
|
||||||
MinimumRect = minimumRect;
|
MinimumSize = minimumRect;
|
||||||
Color = color;
|
Color = color;
|
||||||
|
|
||||||
_defaultColor = color;
|
_defaultColor = color;
|
||||||
@@ -65,6 +65,11 @@ public class RectangleWidget : Widget
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnUpdate()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private Color _defaultColor;
|
private Color _defaultColor;
|
||||||
private Color _hoverColor;
|
private Color _hoverColor;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Xml.Serialization;
|
|
||||||
using Voile.Input;
|
using Voile.Input;
|
||||||
using Voile.Rendering;
|
using Voile.Rendering;
|
||||||
|
|
||||||
@@ -8,13 +7,8 @@ namespace Voile.UI.Widgets;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A base class for all UI widgets.
|
/// A base class for all UI widgets.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class Widget : IElement, IRenderableElement, IInputElement, IResizeableElement, IUpdatableElement, IAnchorableElement
|
public abstract class Widget : UIElement, IInputElement
|
||||||
{
|
{
|
||||||
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()
|
public Widget()
|
||||||
{
|
{
|
||||||
MarkDirty();
|
MarkDirty();
|
||||||
@@ -32,90 +26,18 @@ public abstract class Widget : IElement, IRenderableElement, IInputElement, IRes
|
|||||||
MarkDirty();
|
MarkDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// </inheritdoc>
|
|
||||||
public abstract Rect MinimumRect { get; }
|
|
||||||
|
|
||||||
public bool Dirty => _isDirty;
|
|
||||||
|
|
||||||
public Anchor Anchor { get; set; }
|
|
||||||
public Vector2 AnchorOffset { get; set; }
|
|
||||||
|
|
||||||
public void ApplyAnchor(Vector2 parentPosition, Rect parentRect)
|
|
||||||
{
|
|
||||||
switch (Anchor)
|
|
||||||
{
|
|
||||||
case Anchor.TopLeft:
|
|
||||||
Position = parentPosition + AnchorOffset;
|
|
||||||
break;
|
|
||||||
case Anchor.TopCenter:
|
|
||||||
var topCenterX = parentRect.Width / 2;
|
|
||||||
var topCenterY = parentPosition.Y;
|
|
||||||
|
|
||||||
Position = new Vector2(parentPosition.X + topCenterX, topCenterY) + AnchorOffset;
|
|
||||||
break;
|
|
||||||
case Anchor.TopRight:
|
|
||||||
Position = new Vector2(parentPosition.X + parentRect.Width, parentPosition.Y);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Anchor.Fill:
|
|
||||||
Position = parentPosition;
|
|
||||||
Size = parentRect;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotImplementedException("This anchor type is not implemented!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when its time to draw this widget.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="renderer"></param>
|
|
||||||
public abstract void Render(RenderSystem renderer, Style style);
|
|
||||||
|
|
||||||
public void Input(UIInputContext context)
|
public void Input(UIInputContext context)
|
||||||
{
|
{
|
||||||
if (context.Handled) return;
|
if (context.Handled || IgnoreInput) return;
|
||||||
|
if (ContainsPoint(context.MousePosition))
|
||||||
|
{
|
||||||
OnInput(context);
|
OnInput(context);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when this widget receives input.
|
/// Called when this widget receives input.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="action">An input action this widget received.</param>
|
/// <param name="action">An input action this widget received.</param>
|
||||||
protected abstract void OnInput(UIInputContext action);
|
protected abstract void OnInput(UIInputContext context);
|
||||||
|
|
||||||
public void Update()
|
|
||||||
{
|
|
||||||
if (!_isDirty) return;
|
|
||||||
_isDirty = false;
|
|
||||||
|
|
||||||
if (Size == Rect.Zero)
|
|
||||||
{
|
|
||||||
Size = MinimumRect;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MarkDirty() => _isDirty = true;
|
|
||||||
|
|
||||||
public void DrawSize(RenderSystem renderer)
|
|
||||||
{
|
|
||||||
renderer.SetTransform(Position, Vector2.Zero);
|
|
||||||
renderer.DrawRectangleOutline(new Vector2(Size.Width, Size.Height), Color.Red, 2.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if this <see cref="Widget"/> contains a point within its confines.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pointPosition">A global position of the point.</param>
|
|
||||||
/// <returns>True if the point is inside the widget; otherwise, false.</returns>
|
|
||||||
public bool ContainsPoint(Vector2 pointPosition)
|
|
||||||
{
|
|
||||||
return pointPosition.X >= Position.X &&
|
|
||||||
pointPosition.Y >= Position.Y &&
|
|
||||||
pointPosition.X <= Position.X + Size.Width &&
|
|
||||||
pointPosition.Y <= Position.Y + Size.Height;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _isDirty = true;
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user