Prepare UIElement and Style for animated style implementation.
This commit is contained in:
@@ -65,6 +65,9 @@ namespace Voile.Resources.DataReaders
|
|||||||
/// <param name="defaultValue">Default value in case this getter fails to get data.</param>
|
/// <param name="defaultValue">Default value in case this getter fails to get data.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
double GetDouble(string key, double defaultValue = 0.0);
|
double GetDouble(string key, double defaultValue = 0.0);
|
||||||
|
|
||||||
|
string GetString(string key, string defaultValue);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a Voile.Color from this data getter.
|
/// Get a Voile.Color from this data getter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -105,6 +105,21 @@ public class TomlDataReader : IStreamDataReader, IDataValidator, IStreamKeyValue
|
|||||||
public double GetDouble(string key, double defaultValue = 0)
|
public double GetDouble(string key, double defaultValue = 0)
|
||||||
=> TryGetNode(key, out var node) && node.IsFloat ? node.AsFloat : defaultValue;
|
=> TryGetNode(key, out var node) && node.IsFloat ? node.AsFloat : defaultValue;
|
||||||
|
|
||||||
|
public string GetString(string key, string defaultValue)
|
||||||
|
{
|
||||||
|
if (!TryGetNode(key, out var node))
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.IsString)
|
||||||
|
{
|
||||||
|
return node.AsString;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
public Color GetColor(string key, Color defaultValue)
|
public Color GetColor(string key, Color defaultValue)
|
||||||
{
|
{
|
||||||
if (!TryGetNode(key, out var node))
|
if (!TryGetNode(key, out var node))
|
||||||
@@ -225,7 +240,6 @@ public class TomlDataReader : IStreamDataReader, IDataValidator, IStreamKeyValue
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private TomlTable? _table;
|
private TomlTable? _table;
|
||||||
private bool _valid;
|
private bool _valid;
|
||||||
|
|
||||||
|
|||||||
@@ -140,10 +140,8 @@ public abstract class Container : UIElement, IParentableElement
|
|||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Render(RenderSystem renderer, Style style)
|
protected override void OnRender(RenderSystem renderer, Style style)
|
||||||
{
|
{
|
||||||
RenderStyleBox(renderer, style);
|
|
||||||
|
|
||||||
foreach (var child in Children)
|
foreach (var child in Children)
|
||||||
{
|
{
|
||||||
if (child is not IRenderableElement renderable) continue;
|
if (child is not IRenderableElement renderable) continue;
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ public class FillContainer : Container
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Render(RenderSystem renderer, Style style)
|
protected override void OnRender(RenderSystem renderer, Style style)
|
||||||
{
|
{
|
||||||
base.Render(renderer, style);
|
base.OnRender(renderer, style);
|
||||||
|
|
||||||
Rect parentSize;
|
Rect parentSize;
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public interface IUpdatableElement
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update this element.
|
/// Update this element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Update();
|
void Update(float dt = 0.0f);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Marks this element as changed, requiring an update.
|
/// Marks this element as changed, requiring an update.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -11,6 +11,16 @@ namespace Voile.UI;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Style
|
public class Style
|
||||||
{
|
{
|
||||||
|
public enum AnimationType
|
||||||
|
{
|
||||||
|
Linear,
|
||||||
|
EaseIn,
|
||||||
|
EaseOut,
|
||||||
|
EaseInOut
|
||||||
|
}
|
||||||
|
|
||||||
|
public float TransitionDuration = 0f;
|
||||||
|
public AnimationType TransitionType = AnimationType.Linear;
|
||||||
|
|
||||||
public Style() { }
|
public Style() { }
|
||||||
|
|
||||||
@@ -78,6 +88,14 @@ public class StyleSheetLoader : ResourceLoader<StyleSheet>
|
|||||||
{
|
{
|
||||||
var style = new Style();
|
var style = new Style();
|
||||||
|
|
||||||
|
string easingName = reader.GetString("TransitionType", "Linear");
|
||||||
|
|
||||||
|
if (!Enum.TryParse<Style.AnimationType>(easingName, true, out var easing))
|
||||||
|
easing = Style.AnimationType.Linear;
|
||||||
|
|
||||||
|
style.TransitionType = easing;
|
||||||
|
|
||||||
|
|
||||||
if (reader.HasKey("BackgroundColor"))
|
if (reader.HasKey("BackgroundColor"))
|
||||||
style.BackgroundColor = reader.GetColor("BackgroundColor", Color.Transparent);
|
style.BackgroundColor = reader.GetColor("BackgroundColor", Color.Transparent);
|
||||||
|
|
||||||
|
|||||||
56
Voile/Source/UI/StyleAnimator.cs
Normal file
56
Voile/Source/UI/StyleAnimator.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
namespace Voile.UI;
|
||||||
|
|
||||||
|
public class StyleAnimator
|
||||||
|
{
|
||||||
|
public bool IsComplete => _elapsed >= _duration;
|
||||||
|
|
||||||
|
public StyleAnimator(Style from, Style to, float duration)
|
||||||
|
{
|
||||||
|
_from = from;
|
||||||
|
_to = to;
|
||||||
|
|
||||||
|
_duration = duration;
|
||||||
|
_elapsed = 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Ease(float t, Style.AnimationType type)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
Style.AnimationType.Linear => t,
|
||||||
|
Style.AnimationType.EaseIn => t * t,
|
||||||
|
Style.AnimationType.EaseOut => t * (2 - t),
|
||||||
|
Style.AnimationType.EaseInOut => t < 0.5f
|
||||||
|
? 2 * t * t
|
||||||
|
: -1 + (4 - 2 * t) * t,
|
||||||
|
_ => t
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Style Update(float deltaTime)
|
||||||
|
{
|
||||||
|
_elapsed = MathF.Min(_elapsed + deltaTime, _duration);
|
||||||
|
float t = _duration == 0 ? 1 : _elapsed / _duration;
|
||||||
|
float easedT = Ease(t, _to.TransitionType);
|
||||||
|
|
||||||
|
return LerpStyle(_from, _to, easedT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Style LerpStyle(Style from, Style to, float t)
|
||||||
|
{
|
||||||
|
var result = new Style()
|
||||||
|
{
|
||||||
|
BackgroundColor = MathUtils.LerpColor(from.BackgroundColor ?? Color.Transparent, to.BackgroundColor ?? Color.Transparent, t),
|
||||||
|
TextColor = MathUtils.LerpColor(from.TextColor ?? Color.Black, to.TextColor ?? Color.Black, t),
|
||||||
|
Padding = MathUtils.LerpSize(from.Padding ?? Size.Zero, to.Padding ?? Size.Zero, t),
|
||||||
|
BorderColor = MathUtils.LerpColor(from.BorderColor ?? Color.Transparent, to.BorderColor ?? Color.Transparent, t),
|
||||||
|
BorderSize = MathUtils.LerpSize(from.BorderSize ?? Size.Zero, to.BorderSize ?? Size.Zero, t),
|
||||||
|
TransitionType = to.TransitionType
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Style _from, _to;
|
||||||
|
private float _duration, _elapsed;
|
||||||
|
}
|
||||||
@@ -91,7 +91,7 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme
|
|||||||
MarkDirty();
|
MarkDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public void Update(float dt = 0.0f)
|
||||||
{
|
{
|
||||||
if (!_dirty) return;
|
if (!_dirty) return;
|
||||||
_dirty = false;
|
_dirty = false;
|
||||||
@@ -107,7 +107,13 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void Render(RenderSystem renderer, Style style);
|
public void Render(RenderSystem renderer, Style style)
|
||||||
|
{
|
||||||
|
RenderStyleBox(renderer, style);
|
||||||
|
OnRender(renderer, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void OnRender(RenderSystem renderer, Style style);
|
||||||
protected abstract void OnUpdate();
|
protected abstract void OnUpdate();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public class Button : Widget
|
|||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Render(RenderSystem renderer, Style style)
|
protected override void OnRender(RenderSystem renderer, Style style)
|
||||||
{
|
{
|
||||||
if (_padding != style.Padding)
|
if (_padding != style.Padding)
|
||||||
{
|
{
|
||||||
@@ -91,11 +91,6 @@ public class Button : Widget
|
|||||||
_padding = style.Padding ?? Voile.Size.Zero;
|
_padding = style.Padding ?? Voile.Size.Zero;
|
||||||
var textColor = style.TextColor ?? Color.Black;
|
var textColor = style.TextColor ?? Color.Black;
|
||||||
|
|
||||||
// renderer.SetTransform(GlobalPosition, Vector2.Zero);
|
|
||||||
// renderer.DrawRectangle(new Vector2(Size.Width, Size.Height), backgroundColor);
|
|
||||||
|
|
||||||
RenderStyleBox(renderer, style);
|
|
||||||
|
|
||||||
var textPosition = new Vector2(GlobalPosition.X + Padding.Left, GlobalPosition.Y + Padding.Top);
|
var textPosition = new Vector2(GlobalPosition.X + Padding.Left, GlobalPosition.Y + Padding.Top);
|
||||||
renderer.SetTransform(textPosition, Vector2.Zero);
|
renderer.SetTransform(textPosition, Vector2.Zero);
|
||||||
renderer.DrawText(_suitableFont, _text, textColor);
|
renderer.DrawText(_suitableFont, _text, textColor);
|
||||||
|
|||||||
@@ -50,10 +50,8 @@ public class Label : Widget
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Render(RenderSystem renderer, Style style)
|
protected override void OnRender(RenderSystem renderer, Style style)
|
||||||
{
|
{
|
||||||
RenderStyleBox(renderer, style);
|
|
||||||
|
|
||||||
renderer.SetTransform(GlobalPosition, Vector2.Zero);
|
renderer.SetTransform(GlobalPosition, Vector2.Zero);
|
||||||
renderer.DrawText(_suitableFont, _text, style.TextColor ?? Color.Black);
|
renderer.DrawText(_suitableFont, _text, style.TextColor ?? Color.Black);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class RectangleWidget : Widget
|
|||||||
_hoverColor = color.Lightened(0.25f);
|
_hoverColor = color.Lightened(0.25f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Render(RenderSystem renderer, Style style)
|
protected override void OnRender(RenderSystem renderer, Style style)
|
||||||
{
|
{
|
||||||
renderer.SetTransform(GlobalPosition, Vector2.Zero);
|
renderer.SetTransform(GlobalPosition, Vector2.Zero);
|
||||||
renderer.DrawRectangle(new Vector2(Size.Width, Size.Height), Color);
|
renderer.DrawRectangle(new Vector2(Size.Width, Size.Height), Color);
|
||||||
|
|||||||
@@ -15,6 +15,18 @@ namespace Voile
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static float Lerp(float a, float b, float t) => t <= 0f ? a : t >= 1f ? b : LerpUnclamped(a, b, t);
|
public static float Lerp(float a, float b, float t) => t <= 0f ? a : t >= 1f ? b : LerpUnclamped(a, b, t);
|
||||||
|
|
||||||
|
public static Size LerpSize(Size a, Size b, float t)
|
||||||
|
{
|
||||||
|
t = Math.Clamp(t, 0f, 1f);
|
||||||
|
|
||||||
|
float left = Lerp(a.Left, b.Left, t);
|
||||||
|
float right = Lerp(a.Right, b.Right, t);
|
||||||
|
float top = Lerp(a.Top, b.Top, t);
|
||||||
|
float bottom = Lerp(a.Bottom, b.Bottom, t);
|
||||||
|
|
||||||
|
return new Size(left, right, top, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
public static Color LerpColor(Color colorA, Color colorB, float t)
|
public static Color LerpColor(Color colorA, Color colorB, float t)
|
||||||
{
|
{
|
||||||
t = Math.Clamp(t, 0f, 1f);
|
t = Math.Clamp(t, 0f, 1f);
|
||||||
|
|||||||
Reference in New Issue
Block a user