From 87e0a69dcf43dcf171b22f671d388909fbf2dd75 Mon Sep 17 00:00:00 2001 From: dnesov Date: Sun, 29 Jun 2025 17:29:47 +0200 Subject: [PATCH] WIP: button widget --- TestGame/TestGame.cs | 30 ++++---- Voile/Source/UI/Containers/MarginContainer.cs | 7 ++ Voile/Source/UI/UISystem.cs | 2 + Voile/Source/UI/Widgets/Button.cs | 74 +++++++++++++++++-- 4 files changed, 90 insertions(+), 23 deletions(-) diff --git a/TestGame/TestGame.cs b/TestGame/TestGame.cs index 00dc823..8c15747 100644 --- a/TestGame/TestGame.cs +++ b/TestGame/TestGame.cs @@ -63,10 +63,19 @@ public class TestGame : Game Input.AddInputMapping("reload", new IInputAction[] { new KeyInputAction(KeyboardKey.R) }); _emitterId = _particleSystem.CreateEmitter(Renderer.WindowSize / 2, _fireEffect); - // _fillContainer.AddChild(_container); - // _marginContainer.AddChild(_container); + var button = new Button("Add element", _defaultFontSet, () => { _container.AddChild(new Label("Hello, World!", _defaultFontSet)); }); + button.Padding = new Margin(8.0f); - _uiSystem.AddElement(_container); + _buttonContainer.AddChild(button); + + var c = new MarginContainer(); + c.AddChild(_container); + + _buttonContainer.AddChild(c); + + _root.AddChild(_buttonContainer); + + _uiSystem.AddElement(_root); } @@ -78,11 +87,6 @@ public class TestGame : Game _particleSystem!.RestartEmitter(_emitterId); } - if (Input.IsActionPressed("accept")) - { - _container.AddChild(new Label("こんにちは世界!", _defaultFontSet)); - } - if (Input.IsActionPressed("cancel") && _container.Children.Count != 0) { var lastChild = _container.Children.Last(); @@ -146,12 +150,6 @@ public class TestGame : Game [NotNull] private Label _label; - private FillContainer _fillContainer = new(); - private MarginContainer _marginContainer = new(new Margin(32.0f)) - { - }; - // private HorizontalContainer _container = new(new Rect(128.0f, 64.0f), new(), 16) - // { - // ConfineToContents = true, - // }; + private FillContainer _root = new(); + private VerticalContainer _buttonContainer = new(16); } \ No newline at end of file diff --git a/Voile/Source/UI/Containers/MarginContainer.cs b/Voile/Source/UI/Containers/MarginContainer.cs index bf3d586..09ccea9 100644 --- a/Voile/Source/UI/Containers/MarginContainer.cs +++ b/Voile/Source/UI/Containers/MarginContainer.cs @@ -32,6 +32,13 @@ public struct Margin } 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 class MarginContainer : Container diff --git a/Voile/Source/UI/UISystem.cs b/Voile/Source/UI/UISystem.cs index 5dfd6b5..1644be4 100644 --- a/Voile/Source/UI/UISystem.cs +++ b/Voile/Source/UI/UISystem.cs @@ -150,6 +150,8 @@ public class UISystem : IUpdatableSystem, IRenderableSystem { var element = elements[i]; + // if (!element.ContainsPoint(context.MousePosition)) continue; + if (element is IInputElement inputElement && !inputElement.IgnoreInput) { inputElement.Input(context); diff --git a/Voile/Source/UI/Widgets/Button.cs b/Voile/Source/UI/Widgets/Button.cs index e2934fd..4485543 100644 --- a/Voile/Source/UI/Widgets/Button.cs +++ b/Voile/Source/UI/Widgets/Button.cs @@ -1,6 +1,8 @@ using System.Numerics; using Voile.Input; using Voile.Rendering; +using Voile.Resources; +using Voile.UI.Containers; namespace Voile.UI.Widgets; @@ -17,13 +19,42 @@ public enum ButtonState /// public class Button : Widget { - public string Label { get; set; } = "Button"; - public override Rect MinimumSize => new Rect(Width: 128.0f, Height: 64.0f); - - public Button(string label, Action pressedAction) + public string Text { - Label = label; + get => _text; set + { + _text = value; + MarkDirty(); + } + } + public override Rect MinimumSize => Padding + _textSize; + + /// + /// to use with this button. + /// + public FontSet FontSet { get; set; } = new(); + public Margin Padding { get; set; } = Margin.Zero; + + public Button(string text, ResourceRef fontOverride, Action pressedAction) + { + _text = text; _pressedAction = pressedAction; + + FontSet.AddFont(fontOverride); + + MarkDirty(); + Update(); + } + + public Button(string text, FontSet fontSet, Action pressedAction) + { + _text = text; + _pressedAction = pressedAction; + + FontSet = fontSet; + + MarkDirty(); + Update(); } public override void Render(RenderSystem renderer, Style style) @@ -31,17 +62,46 @@ public class Button : Widget // TODO: use a button color from style. renderer.SetTransform(GlobalPosition, Vector2.Zero); renderer.DrawRectangle(new Vector2(MinimumSize.Width, MinimumSize.Height), new Color(0.25f, 0.25f, 0.25f)); + + var textPosition = new Vector2(GlobalPosition.X + Padding.Left, GlobalPosition.Y + Padding.Top); + renderer.SetTransform(textPosition, Vector2.Zero); + renderer.DrawText(_suitableFont, _text, Color.White); } protected override void OnInput(UIInputContext action) { - + if (action.MouseReleased && ContainsPoint(action.MousePosition)) + { + _pressedAction?.Invoke(); + } } protected override void OnUpdate() { - throw new NotImplementedException(); + ResourceRef fontRef = ResourceRef.Empty(); + foreach (var c in _text) + { + if (FontSet.TryGetFontFor(c, out var fallbackFont)) + { + if (fallbackFont != fontRef) + { + fontRef = fallbackFont; + } + } + } + + _suitableFont = fontRef; + + var font = _suitableFont.Value; + _textSize = font.Measure(_text); + + Size = Padding + _textSize; } private Action _pressedAction; + + private ResourceRef _suitableFont = ResourceRef.Empty(); + + private string _text = "Hello, World!"; + private Rect _textSize = Rect.Zero; } \ No newline at end of file