We got CSS at home

This commit is contained in:
2025-06-29 22:21:13 +02:00
parent 681496d812
commit 207c8a20a4
15 changed files with 404 additions and 292 deletions

View File

@@ -0,0 +1,46 @@
[Button]
BackgroundColor = "#0f62fe"
TextColor = "#37eb34"
Padding = 16.0
# Creates an empty rule for Button.Normal.
# This will inherit style from Button, this is a temporary workaround.
[Button.Normal]
[Button.Hovered]
BackgroundColor = "#0353e9"
[Button.Pressed]
BackgroundColor = "#002d9c"
[Button.Danger]
TextColor = "#ffffff"
[Button.Danger.Normal]
BackgroundColor = "#da1e28"
[Button.Danger.Hovered]
BackgroundColor = "#ba1b23"
[Button.Danger.Pressed]
BackgroundColor = "#750e13"
[Button.Outline]
BackgroundColor = [0, 0, 0, 0]
BorderSize = 1.0
BorderColor = "#0f62fe"
TextColor = "#0353e9"
[Button.Outline.Normal]
TextColor = "#0353e9"
[Button.Outline.Hovered]
BackgroundColor = "#0353e9"
[Button.Outline.Pressed]
BackgroundColor = "#002d9c"
BorderColor = [0, 0, 0, 0]
# Default background color for all Container derived classes.
[Container]
BackgroundColor = "#e0e0e0"

View File

@@ -19,7 +19,7 @@ public class TestGame : Game
{
InitializeSystemsDefault();
_uiSystem = new UISystem(Input, StyleSheet.Default);
_uiSystem = new UISystem(Input);
// _uiSystem.RenderDebugRects = true;
_particleSystem = new ParticleSystem();
@@ -36,6 +36,7 @@ public class TestGame : Game
protected override void LoadResources()
{
ResourceManager.AddResourceLoaderAssociation(new ParticleEmitterSettingsResourceLoader());
ResourceManager.AddResourceLoaderAssociation(new StyleSheetLoader());
if (!ResourceManager.TryLoad("fonts/Inter-Regular.ttf", out _font))
{
@@ -55,27 +56,32 @@ public class TestGame : Game
throw new Exception("Failed to load emitter settings!");
}
if (ResourceManager.TryLoad("default.style.toml", out _styleSheet))
{
}
_defaultFontSet = new([_font, _jpFont]);
}
protected override void Ready()
{
Input.AddInputMapping("reload", new IInputAction[] { new KeyInputAction(KeyboardKey.R) });
_emitterId = _particleSystem.CreateEmitter(Renderer.WindowSize / 2, _fireEffect);
// _emitterId = _particleSystem.CreateEmitter(Renderer.WindowSize / 2, _fireEffect);
var addButton = new Button("Add element", _defaultFontSet, () => { _container.AddChild(new Label("Hello, World!", _defaultFontSet)); });
_uiSystem.SetStyleSheet(_styleSheet);
var removeButton = new Button("Remove element", _defaultFontSet, () =>
{
if (_container.Children.Count == 0) return;
var lastChild = _container.Children.Last();
_container.RemoveChild(lastChild);
});
var addButton = new Button("Default button", _defaultFontSet);
var removeButton = new Button("Danger button", _defaultFontSet);
removeButton.StyleVariant = "Danger";
// _buttonContainer.AddChild(addButton);
// _buttonContainer.AddChild(removeButton);
var outlineButton = new Button("Outline button", _defaultFontSet);
outlineButton.StyleVariant = "Outline";
_buttonContainer.AddChild(addButton);
_buttonContainer.AddChild(removeButton);
var c = new HorizontalContainer()
{
@@ -86,11 +92,12 @@ public class TestGame : Game
c.AddChild(addButton);
c.AddChild(removeButton);
c.AddChild(outlineButton);
var vc = new VerticalContainer(0.0f);
vc.AddChild(c);
var f = new MarginContainer(new Margin(0.0f));
var f = new MarginContainer(new Size(0.0f));
f.AddChild(_container);
vc.AddChild(f);
@@ -105,7 +112,7 @@ public class TestGame : Game
if (Input.IsActionPressed("reload"))
{
ResourceManager.Reload();
_particleSystem!.RestartEmitter(_emitterId);
// _particleSystem!.RestartEmitter(_emitterId);
}
}
@@ -147,6 +154,7 @@ public class TestGame : Game
private ResourceRef<ParticleEmitterSettingsResource> _fireEffect;
private ResourceRef<Font> _font;
private ResourceRef<Font> _jpFont;
private ResourceRef<StyleSheet> _styleSheet;
private FontSet _defaultFontSet;

View File

@@ -6,6 +6,7 @@ namespace Voile
/// </summary>
public record struct Color
{
public static readonly Color Transparent = new(1.0f, 1.0f, 1.0f, 0.0f);
public static readonly Color AliceBlue = new(0xF0F8FF);
public static readonly Color AntiqueWhite = new(0xFAEBD7);
public static readonly Color Aqua = new(0x00FFFF);

View File

@@ -21,3 +21,61 @@ public record Rect(float Width = 0.0f, float Height = 0.0f)
public static bool operator >=(Rect left, Rect right) => left.CompareTo(right) >= 0;
public static bool operator <=(Rect left, Rect right) => left.CompareTo(right) <= 0;
}
/// <summary>
/// Represents the size offsets applied around a rectangle.
/// </summary>
public struct Size : IEquatable<Size>
{
public float Left;
public float Right;
public float Top;
public float Bottom;
public Size(float uniform)
{
Left = Right = Top = Bottom = uniform;
}
public Size(float horizontal, float vertical)
{
Left = Right = horizontal;
Top = Bottom = vertical;
}
public Size(float left, float right, float top, float bottom)
{
Left = left;
Right = right;
Top = top;
Bottom = bottom;
}
public static Size Zero => new Size(0);
public static Rect operator +(Size margin, Rect rect) =>
new Rect(rect.Width + margin.Left + margin.Right,
rect.Height + margin.Top + margin.Bottom);
public static Rect operator +(Rect rect, Size margin) =>
margin + rect;
public static bool operator ==(Size a, Size b) =>
a.Equals(b);
public static bool operator !=(Size a, Size b) =>
!a.Equals(b);
public bool Equals(Size other) =>
Left == other.Left &&
Right == other.Right &&
Top == other.Top &&
Bottom == other.Bottom;
public override bool Equals(object? obj) =>
obj is Size other && Equals(other);
public override int GetHashCode() =>
HashCode.Combine(Left, Right, Top, Bottom);
}

View File

@@ -79,5 +79,7 @@ namespace Voile.Resources.DataReaders
/// <param name="defaultValue">Default value in case this getter fails to get data.</param>
/// <returns></returns>
Vector2 GetVector2(string key, Vector2 defaultValue);
T[] GetArray<T>(string key, T[] defaultValue);
}
}

View File

@@ -9,163 +9,114 @@ namespace Voile.Resources.DataReaders;
/// </summary>
public class TomlDataReader : IStreamDataReader, IDataValidator, IStreamKeyValueGetter
{
public string ExpectedHeader { get; private set; } = string.Empty;
public TomlDataReader(string expectedHeader)
{
ExpectedHeader = expectedHeader;
}
public TomlDataReader() { }
public void Read(Stream data)
{
using (var reader = new StreamReader(data))
{
using var reader = new StreamReader(data);
_table = TOML.Parse(reader);
_valid = _table.HasKey(ExpectedHeader);
_valid = _table != null;
}
public bool Valid() => _valid;
public bool HasKey(string key)
{
return _table != null &&
_table.HasKey(key);
}
public IEnumerable<string> GetSubKeys()
{
if (_table == null)
return Enumerable.Empty<string>();
return _table.Keys
.Where(k => _table[k].IsTable)
.ToList();
}
public IEnumerable<string> GetSubKeysRecursive(string prefix = "")
{
if (_table == null)
yield break;
foreach (var key in _table.Keys)
{
var fullKey = string.IsNullOrEmpty(prefix) ? key : $"{prefix}.{key}";
if (_table[key].IsTable)
{
var subReader = GetSubReader(key);
if (subReader != null)
{
foreach (var subKey in subReader.GetSubKeysRecursive(fullKey))
yield return subKey;
yield return fullKey;
}
}
}
}
public IEnumerable<string> GetSubKeys(string subPath)
{
var subReader = GetSubReader(subPath);
if (subReader?._table == null)
return Enumerable.Empty<string>();
return subReader._table.Keys
.Where(k => subReader._table[k].IsTable)
.ToList();
}
public TomlDataReader? GetSubReader(string path)
{
var current = _table;
foreach (var part in path.Split('.'))
{
if (current == null || !current.HasKey(part) || !current[part].IsTable)
return null;
current = current[part].AsTable;
}
return new TomlDataReader { _table = current, _valid = true };
}
public bool GetBool(string key, bool defaultValue = false)
{
if (_table is null)
{
return defaultValue;
}
var dataTable = _table[ExpectedHeader];
if (!dataTable.HasKey(key))
{
return defaultValue;
}
var tableValue = dataTable[key];
if (!tableValue.IsBoolean)
{
return defaultValue;
}
return tableValue.AsBoolean;
}
=> TryGetNode(key, out var node) && node.IsBoolean ? node.AsBoolean : defaultValue;
public int GetInt(string key, int defaultValue = 0)
{
if (_table is null)
{
return defaultValue;
}
var dataTable = _table[ExpectedHeader];
if (!dataTable.HasKey(key))
{
return defaultValue;
}
var tableValue = dataTable[key];
if (!tableValue.IsInteger)
{
return defaultValue;
}
return tableValue.AsInteger;
}
=> TryGetNode(key, out var node) && node.IsInteger ? node.AsInteger : defaultValue;
public long GetLong(string key, long defaultValue = 0)
{
if (_table is null)
{
return defaultValue;
}
var dataTable = _table[ExpectedHeader];
if (!dataTable.HasKey(key))
{
return defaultValue;
}
var tableValue = dataTable[key];
if (!tableValue.IsInteger)
{
return defaultValue;
}
return tableValue.AsInteger.Value;
}
=> TryGetNode(key, out var node) && node.IsInteger ? node.AsInteger.Value : defaultValue;
public float GetFloat(string key, float defaultValue = 0)
{
if (_table is null)
{
if (!TryGetNode(key, out var node))
return defaultValue;
}
var dataTable = _table[ExpectedHeader];
if (!dataTable.HasKey(key))
{
if (node.IsFloat) return node.AsFloat;
if (node.IsInteger) return node.AsInteger;
return defaultValue;
}
var tableValue = dataTable[key];
if (!tableValue.IsFloat)
{
if (tableValue.IsInteger) return (float)tableValue.AsInteger.Value;
return defaultValue;
}
return tableValue.AsFloat;
}
public double GetDouble(string key, double defaultValue = 0)
{
if (_table is null)
{
return defaultValue;
}
var dataTable = _table[ExpectedHeader];
if (!dataTable.HasKey(key))
{
return defaultValue;
}
if (!dataTable.IsFloat)
{
return defaultValue;
}
return dataTable.AsFloat.Value;
}
=> TryGetNode(key, out var node) && node.IsFloat ? node.AsFloat : defaultValue;
public Color GetColor(string key, Color defaultValue)
{
if (_table is null)
{
if (!TryGetNode(key, out var node))
return defaultValue;
}
var dataTable = _table[ExpectedHeader];
if (!dataTable.HasKey(key))
if (node.IsInteger)
{
return defaultValue;
return new Color(node.AsInteger);
}
var colorNode = dataTable[key];
if (colorNode.IsInteger)
else if (node.IsArray)
{
return new Color(colorNode.AsInteger);
}
else if (colorNode.IsArray)
{
var colorArray = colorNode.AsArray;
var colorArray = node.AsArray;
var rNode = colorArray[0];
var gNode = colorArray[1];
@@ -185,9 +136,9 @@ public class TomlDataReader : IStreamDataReader, IDataValidator, IStreamKeyValue
return new Color((byte)r, (byte)g, (byte)b, (byte)a);
}
else if (colorNode.IsString)
else if (node.IsString)
{
var colorHexString = colorNode.AsString.Value;
var colorHexString = node.AsString.Value;
return Color.FromHexString(colorHexString);
}
else
@@ -198,32 +149,56 @@ public class TomlDataReader : IStreamDataReader, IDataValidator, IStreamKeyValue
public Vector2 GetVector2(string key, Vector2 defaultValue)
{
if (_table is null)
{
if (!TryGetNode(key, out var node) || !node.IsArray || node.AsArray.RawArray.Count != 2)
return defaultValue;
var arr = node.AsArray;
return new Vector2(arr[0], arr[1]);
}
var dataTable = _table[ExpectedHeader];
if (!dataTable.HasKey(key))
public T[] GetArray<T>(string key, T[] defaultValue)
{
return defaultValue;
throw new NotImplementedException("Generic array reading not implemented yet.");
}
var vector2Node = dataTable[key];
if (!vector2Node.IsArray)
private bool TryGetNode(string key, out TomlNode node)
{
return defaultValue;
node = null!;
if (_table == null)
return false;
var current = _table;
var parts = key.Split('.');
for (int i = 0; i < parts.Length; i++)
{
if (!current.HasKey(parts[i]))
return false;
var child = current[parts[i]];
if (i == parts.Length - 1)
{
node = child;
return true;
}
var vector2Array = vector2Node.AsArray;
if (!child.IsTable)
return false;
return new Vector2(vector2Array[0], vector2Array[1]);
current = child.AsTable;
}
public bool Valid() => _valid;
return false;
}
private TomlTable? _table;
private bool _valid;
// Internal use for subreaders
private TomlDataReader(TomlTable table)
{
_table = table;
_valid = true;
}
}

View File

@@ -1,17 +0,0 @@
using Voile.UI;
namespace Voile.Resources;
public class StyleLoader : ResourceLoader<Style>
{
public override IEnumerable<string> SupportedExtensions =>
[
".toml"
];
protected override Style LoadResource(string path)
{
// TODO: implement loading styles.
return new Style(string.Empty);
}
}

View File

@@ -351,7 +351,6 @@ namespace Voile.Resources
{ typeof(Sound), new SoundLoader()},
{typeof(Texture2d), new Texture2dLoader()},
{typeof(Font), new FontLoader()},
{ typeof(Style), new StyleLoader()}
};
private static readonly Dictionary<Type, object> _resourceSaverAssociations = new()

View File

@@ -62,7 +62,7 @@ public class ParticleEmitterSettingsResourceLoader : ResourceLoader<ParticleEmit
{
var settings = new ParticleEmitterSettings();
var reader = new TomlDataReader("ParticleEmitterSettings");
var reader = new TomlDataReader();
reader.Read(VirtualFileSystem.Read(path));
settings.Local = reader.GetBool("Local", true);

View File

@@ -148,7 +148,7 @@ public abstract class Container : UIElement, IParentableElement
{
if (child is not IRenderableElement renderable) continue;
if (!child.TryGetStyle(StyleSheet, out var childStyle))
if (!child.TryGetStyle(StyleSheet.Value, out var childStyle))
{
childStyle = new Style();
}

View File

@@ -2,79 +2,21 @@ using System.Numerics;
namespace Voile.UI.Containers;
/// <summary>
/// Represents the margin offsets applied around an element.
/// </summary>
public struct Margin : IEquatable<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 static Rect operator +(Margin margin, Rect rect) =>
new Rect(rect.Width + margin.Left + margin.Right,
rect.Height + margin.Top + margin.Bottom);
public static Rect operator +(Rect rect, Margin margin) =>
margin + rect;
public static bool operator ==(Margin a, Margin b) =>
a.Equals(b);
public static bool operator !=(Margin a, Margin b) =>
!a.Equals(b);
public bool Equals(Margin other) =>
Left == other.Left &&
Right == other.Right &&
Top == other.Top &&
Bottom == other.Bottom;
public override bool Equals(object? obj) =>
obj is Margin other && Equals(other);
public override int GetHashCode() =>
HashCode.Combine(Left, Right, Top, Bottom);
}
public class MarginContainer : Container
{
/// <summary>
/// The margin to apply around the contents of this container.
/// </summary>
public Margin Margin { get; set; }
public Size Margin { get; set; }
/// <summary>
/// Specifies if this <see cref="MarginContainer"/> will fill to parent size.
/// </summary>
public bool Fill { get; set; } = true;
public MarginContainer() : this(new Margin()) { }
public MarginContainer() : this(new Size()) { }
public MarginContainer(Margin margin)
public MarginContainer(Size margin)
{
Margin = margin;
}

View File

@@ -1,29 +1,116 @@
using System.Diagnostics.CodeAnalysis;
using Voile.Resources;
using Voile.Resources.DataReaders;
using Voile.UI.Containers;
using Voile.VFS;
namespace Voile.UI;
/// <summary>
/// A resource containing UI style settings.
/// UI style settings.
/// </summary>
public class Style : TextDataResource
public class Style
{
public Style(string path) : base(path)
{
}
public Style() : base(string.Empty) { }
public Style() { }
public Margin Padding { get; set; }
public Color BackgroundColor { get; set; }
public Margin BorderSize { get; set; }
public Color BorderColor { get; set; }
public Size Padding { get; set; }
public Color? BackgroundColor { get; set; }
public Size BorderSize { get; set; }
public Color? BorderColor { get; set; }
public float CornerRadius { get; set; }
public Color TextColor { get; set; } = Color.White;
}
public class StyleSheet : TextDataResource
public class StyleSheetLoader : ResourceLoader<StyleSheet>
{
public override IEnumerable<string> SupportedExtensions => [".toml"];
protected override StyleSheet LoadResource(string path)
{
var result = new StyleSheet(path);
var allStyles = new Dictionary<string, Style>();
using var stream = VirtualFileSystem.Read(path);
_reader.Read(stream);
foreach (var styleKey in _reader.GetSubKeysRecursive())
{
var subReader = _reader.GetSubReader(styleKey);
if (subReader == null || !subReader.Valid())
continue;
var style = ParseStyle(subReader, styleKey);
if (style != null)
{
allStyles[styleKey] = style;
}
}
foreach (var kvp in allStyles)
{
var finalStyle = GetMergedStyle(kvp.Key, allStyles);
result.Add(kvp.Key, finalStyle);
}
return result;
}
private Style ParseStyle(TomlDataReader reader, string input)
{
var style = new Style();
if (reader.HasKey("BackgroundColor"))
style.BackgroundColor = reader.GetColor("BackgroundColor", Color.Transparent);
if (reader.HasKey("TextColor"))
style.TextColor = reader.GetColor("TextColor", Color.Black);
if (reader.HasKey("Padding"))
style.Padding = new Size(reader.GetFloat("Padding"));
if (reader.HasKey("BorderSize"))
style.BorderSize = new Size(reader.GetFloat("BorderSize"));
if (reader.HasKey("BorderColor"))
style.BorderColor = reader.GetColor("BorderColor", Color.Transparent);
return style;
}
private Style GetMergedStyle(string fullKey, Dictionary<string, Style> allStyles)
{
var parts = fullKey.Split('.');
var merged = new Style();
for (int i = 1; i <= parts.Length; i++)
{
var subKey = string.Join('.', parts.Take(i));
if (allStyles.TryGetValue(subKey, out var parentStyle))
{
merged = MergeStyles(merged, parentStyle);
}
}
return merged;
}
private Style MergeStyles(Style baseStyle, Style overrideStyle)
{
return new Style
{
BackgroundColor = overrideStyle.BackgroundColor != default ? overrideStyle.BackgroundColor : baseStyle.BackgroundColor,
TextColor = overrideStyle.TextColor != default ? overrideStyle.TextColor : baseStyle.TextColor,
Padding = overrideStyle.Padding != default ? overrideStyle.Padding : baseStyle.Padding,
BorderSize = overrideStyle.BorderSize != default ? overrideStyle.BorderSize : baseStyle.BorderSize,
BorderColor = overrideStyle.BorderColor != default ? overrideStyle.BorderColor : baseStyle.BorderColor,
};
}
private readonly TomlDataReader _reader = new();
}
public class StyleSheet : Resource
{
public StyleSheet(string path) : base(path)
{
@@ -34,6 +121,8 @@ public class StyleSheet : TextDataResource
_styles = styles;
}
public void Add(string key, Style style) => _styles.Add(key, style);
public bool TryGet(string styleName, [NotNullWhen(true)] out Style? style)
{
return _styles.TryGetValue(styleName, out style);
@@ -45,54 +134,54 @@ public class StyleSheet : TextDataResource
{
TextColor = Color.FromHexString("#161616"),
BackgroundColor = Color.DarkRed,
BorderSize = new Margin(2.0f),
BorderSize = new Size(2.0f),
BorderColor = Color.Red
}},
{ "Button", new Style()
{
Padding = new Margin(8.0f),
Padding = new Size(8.0f),
BackgroundColor = Color.FromHexString("#0f62fe"),
TextColor = Color.FromHexString("#ffffff"),
}},
{"Button.Normal", new Style()
{
Padding = new Margin(8.0f),
Padding = new Size(8.0f),
BackgroundColor = Color.FromHexString("#0f62fe"),
TextColor = Color.FromHexString("#ffffff"),
}},
{"Button.Hovered", new Style()
{
Padding = new Margin(8.0f),
Padding = new Size(8.0f),
BackgroundColor = Color.FromHexString("#0353e9"),
TextColor = Color.FromHexString("#ffffff"),
}},
{"Button.Pressed", new Style()
{
Padding = new Margin(8.0f),
Padding = new Size(8.0f),
BackgroundColor = Color.FromHexString("#002d9c"),
TextColor = Color.FromHexString("#ffffff"),
}},
{"Button.Danger", new Style()
{
Padding = new Margin(8.0f),
Padding = new Size(8.0f),
BackgroundColor = Color.FromHexString("#da1e28"),
TextColor = Color.FromHexString("#ffffff"),
}},
{"Button.Danger.Normal", new Style()
{
Padding = new Margin(8.0f),
Padding = new Size(8.0f),
BackgroundColor = Color.FromHexString("#da1e28"),
TextColor = Color.FromHexString("#ffffff"),
}},
{"Button.Danger.Hovered", new Style()
{
Padding = new Margin(8.0f),
Padding = new Size(8.0f),
BackgroundColor = Color.FromHexString("#ba1b23"),
TextColor = Color.FromHexString("#ffffff"),
}},
{"Button.Danger.Pressed", new Style()
{
Padding = new Margin(8.0f),
Padding = new Size(8.0f),
BackgroundColor = Color.FromHexString("#750e13"),
TextColor = Color.FromHexString("#ffffff"),
}},

View File

@@ -29,8 +29,8 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme
/// </summary>
public virtual string[]? StyleModifiers { get; }
public StyleSheet StyleSheet => Parent?.StyleSheet ?? StyleSheetOverride;
public StyleSheet StyleSheetOverride { get; set; } = new(string.Empty);
public ResourceRef<StyleSheet> StyleSheet => Parent?.StyleSheet ?? StyleSheetOverride;
public ResourceRef<StyleSheet> StyleSheetOverride { get; set; } = ResourceRef<StyleSheet>.Empty();
/// <summary>
/// Parent <see cref="UIElement"/> of this element.
@@ -117,8 +117,8 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme
/// <param name="style"></param>
protected void RenderStyleBox(RenderSystem renderer, Style style)
{
var backgroundColor = style.BackgroundColor;
var borderColor = style.BorderColor;
var backgroundColor = style.BackgroundColor ?? Color.Transparent;
var borderColor = style.BorderColor ?? Color.Transparent;
var borderSize = style.BorderSize;
renderer.SetTransform(GlobalPosition, Vector2.Zero);

View File

@@ -1,10 +1,11 @@
using System.Numerics;
using Voile.Input;
using Voile.Rendering;
using Voile.Resources;
namespace Voile.UI;
public class UISystem : IUpdatableSystem, IRenderableSystem
public class UISystem : IUpdatableSystem, IRenderableSystem, IReloadableSystem
{
public IReadOnlyList<IElement> Elements => _elements;
@@ -14,23 +15,20 @@ public class UISystem : IUpdatableSystem, IRenderableSystem
public UISystem(InputSystem inputSystem)
{
_styleSheet = StyleSheet.Default;
_input = inputSystem;
}
public UISystem(InputSystem inputSystem, StyleSheet styleSheet)
public UISystem(InputSystem inputSystem, List<UIElement> elements)
{
_input = inputSystem;
_styleSheet = styleSheet;
}
public UISystem(InputSystem inputSystem, StyleSheet styleSheet, List<UIElement> elements)
{
_input = inputSystem;
_styleSheet = styleSheet;
_elements = elements;
}
public void SetStyleSheet(ResourceRef<StyleSheet> styleSheet)
{
_styleSheet = styleSheet;
}
public void AddElement(UIElement element)
{
element.StyleSheetOverride = _styleSheet;
@@ -60,11 +58,11 @@ public class UISystem : IUpdatableSystem, IRenderableSystem
{
if (element is IRenderableElement renderable)
{
// TODO: normally you'd load a default style if the one supplied is empty,
// but for now this will do.
if (!_styleSheet.TryGet(element.StyleName, out var style))
var styleSheet = _styleSheet.Value;
if (!styleSheet.TryGet(element.StyleName, out var style))
{
style = new Style(string.Empty);
style = new Style();
}
renderable.Render(renderer, style);
@@ -80,6 +78,11 @@ public class UISystem : IUpdatableSystem, IRenderableSystem
}
}
public void Reload()
{
throw new NotImplementedException();
}
private void DrawDebugForElement(RenderSystem renderer, UIElement element)
{
var size = new Vector2(element.Size.Width, element.Size.Height);
@@ -173,7 +176,7 @@ public class UISystem : IUpdatableSystem, IRenderableSystem
return false;
}
private StyleSheet _styleSheet;
private ResourceRef<StyleSheet> _styleSheet;
private List<UIElement> _elements = new();
private InputSystem _input;

View File

@@ -35,7 +35,7 @@ public class Button : Widget
/// <see cref="FontSet"/> to use with this button.
/// </summary>
public FontSet FontSet { get; set; } = new();
public Margin Padding
public Size Padding
{
get => _padding; set
{
@@ -60,6 +60,16 @@ public class Button : Widget
Update();
}
public Button(string text, FontSet fontSet)
{
_text = text;
FontSet = fontSet;
MarkDirty();
Update();
}
public Button(string text, FontSet fontSet, Action pressedAction)
{
_text = text;
@@ -73,10 +83,6 @@ public class Button : Widget
public override void Render(RenderSystem renderer, Style style)
{
// TODO: use a button color from style.
var backgroundColor = style.BackgroundColor;
if (_padding != style.Padding)
{
MarkDirty();
@@ -153,14 +159,14 @@ public class Button : Widget
Size = _padding + _textSize;
}
private Action _pressedAction;
private Action? _pressedAction;
private ResourceRef<Font> _suitableFont = ResourceRef<Font>.Empty();
private string _text = "Hello, World!";
private Rect _textSize = Rect.Zero;
private Margin _padding;
private Size _padding;
private bool _isHeldDown;
}