diff --git a/DaggerFramework/Source/Rendering/RaylibRenderer.cs b/DaggerFramework/Source/Rendering/RaylibRenderer.cs index adc5b10..eb01ebb 100644 --- a/DaggerFramework/Source/Rendering/RaylibRenderer.cs +++ b/DaggerFramework/Source/Rendering/RaylibRenderer.cs @@ -7,14 +7,26 @@ namespace DaggerFramework.Rendering { public class RaylibRenderer : Renderer { - public override Vector2 WindowSize => _windowSize; + public override Vector2 WindowSize => new Vector2(Raylib.GetScreenWidth(), Raylib.GetScreenHeight()); public override bool ShouldRun => !WindowShouldClose(); - public override void CreateWindow(string title, Vector2 size) + // public override void CreateWindow(string title, Vector2 size) + // { + // Raylib.SetTraceLogLevel(TraceLogLevel.LOG_NONE); + // _windowSize = size; + // Raylib.InitWindow((int)_windowSize.X, (int)_windowSize.Y, title); + // } + + public override void CreateWindow(WindowSettings windowSettings) { Raylib.SetTraceLogLevel(TraceLogLevel.LOG_NONE); - _windowSize = size; - Raylib.InitWindow((int)_windowSize.X, (int)_windowSize.Y, title); + _windowSize = windowSettings.Size; + + ConfigFlags windowFlags = 0; + windowFlags |= windowSettings.Resizable ? ConfigFlags.FLAG_WINDOW_RESIZABLE : 0; + + Raylib.InitWindow((int)_windowSize.X, (int)_windowSize.Y, windowSettings.Title); + Raylib.SetWindowState(windowFlags); } public override void SetWindowTitle(string title) @@ -179,6 +191,7 @@ namespace DaggerFramework.Rendering // Fullscreen flags |= settings.Fullscreen ? ConfigFlags.FLAG_FULLSCREEN_MODE : 0; + Raylib.SetConfigFlags(flags); } diff --git a/DaggerFramework/Source/Rendering/Renderer.cs b/DaggerFramework/Source/Rendering/Renderer.cs index cfa6881..b40cd14 100644 --- a/DaggerFramework/Source/Rendering/Renderer.cs +++ b/DaggerFramework/Source/Rendering/Renderer.cs @@ -32,15 +32,10 @@ namespace DaggerFramework.Rendering /// public abstract Vector2 WindowSize { get; } /// - /// Creates the window with a given title and size. + /// Creates a window. /// - /// Title of the window. - /// Vector2 representing size. - public abstract void CreateWindow(string title, Vector2 size); - public void CreateWindow(WindowSettings windowSettings) - { - CreateWindow(windowSettings.Title, windowSettings.Size); - } + /// Window settings to use to create the window. + public abstract void CreateWindow(WindowSettings windowSettings); // TODO: use properties for these. public abstract void SetWindowTitle(string title); @@ -151,6 +146,7 @@ namespace DaggerFramework.Rendering { public string Title; public Vector2 Size = new Vector2(640, 480); + public bool Resizable { get; set; } public WindowSettings(string title, Vector2 size) { diff --git a/DaggerFramework/Source/Rendering/StandardRenderer.cs b/DaggerFramework/Source/Rendering/StandardRenderer.cs index afe337e..a38faac 100644 --- a/DaggerFramework/Source/Rendering/StandardRenderer.cs +++ b/DaggerFramework/Source/Rendering/StandardRenderer.cs @@ -49,9 +49,6 @@ namespace DaggerFramework.Rendering _gl.Clear((uint)ClearBufferMask.ColorBufferBit); } - /// - public override void CreateWindow(string title, Vector2 size) => CreateWindowUnsafe(title, size); - /// public override void Shutdown() { @@ -176,6 +173,10 @@ namespace DaggerFramework.Rendering throw new NotImplementedException(); } + public override void CreateWindow(WindowSettings windowSettings) + { + throw new NotImplementedException(); + } private GL _gl; private Glfw _glfw; diff --git a/DaggerFramework/Source/SceneGraph/Scene.cs b/DaggerFramework/Source/SceneGraph/Scene.cs index e853ae4..ef36dd1 100644 --- a/DaggerFramework/Source/SceneGraph/Scene.cs +++ b/DaggerFramework/Source/SceneGraph/Scene.cs @@ -77,7 +77,7 @@ namespace DaggerFramework.SceneGraph private void SetupRenderer() { - Renderer.CreateWindow("Game", new Vector2(1280, 720)); + // Renderer.CreateWindow("Game", new Vector2(1280, 720)); Renderer.Initialize(new RendererSettings { Msaa = Msaa.Msaa4x, UseVSync = true }); Renderer.SetTargetFps(60); } diff --git a/DaggerFramework/Source/UI/Container.cs b/DaggerFramework/Source/UI/Container.cs new file mode 100644 index 0000000..0d0e21b --- /dev/null +++ b/DaggerFramework/Source/UI/Container.cs @@ -0,0 +1,63 @@ +using System.Numerics; +using DaggerFramework.Rendering; + +namespace DaggerFramework.UI; + +/// +/// A basic container for UI elements. All container's children will update their constraints based on container's sizing and positioning. +/// +public class Container : UIElement +{ + /// + /// Updates the sizes of the container and rearranges its children. + /// + /// + /// + public void UpdateRect(Vector2 position, Vector2 size) + { + Rect.Position = position; + + UpdateSize(size); + RearrangeChildren(); + } + + protected void RearrangeChildren() + { + int idx = 0; + foreach (var child in children) + { + if (child is Container container) + { + container.UpdateRect(Rect.Position, Rect.Size); + } + RearrangeChild(idx, child); + idx++; + } + } + + protected virtual void RearrangeChild(int idx, UIElement child) { } + + protected override void OnRender(Renderer renderer) + { + + } + + private void UpdateSize(Vector2 baseSize) + { + if (parent == null) + { + Rect.Size = baseSize; + return; + } + + if (VerticalSizeFlags == SizeFlags.Fill) + { + Rect.Size = new Vector2(Rect.Size.X, baseSize.Y * ExpandRatio.Y); + } + + if (HorizontalSizeFlags == SizeFlags.Fill) + { + Rect.Size = new Vector2(baseSize.X * ExpandRatio.X, Rect.Size.Y); + } + } +} \ No newline at end of file diff --git a/DaggerFramework/Source/UI/MarginPanel.cs b/DaggerFramework/Source/UI/MarginPanel.cs new file mode 100644 index 0000000..d2ce4dd --- /dev/null +++ b/DaggerFramework/Source/UI/MarginPanel.cs @@ -0,0 +1,19 @@ +using System.Numerics; + +namespace DaggerFramework.UI; + +public class MarginPanel : Panel +{ + public Vector2 RelativeMargin { get; set; } + public MarginPanel(PanelStyle style) : base(style) + { + } + + protected override void RearrangeChild(int idx, UIElement child) + { + base.RearrangeChild(idx, child); + + var rect = child.Rect; + rect.Position = Rect.Size * RelativeMargin; + } +} \ No newline at end of file diff --git a/DaggerFramework/Source/UI/Panel.cs b/DaggerFramework/Source/UI/Panel.cs new file mode 100644 index 0000000..a3a67b3 --- /dev/null +++ b/DaggerFramework/Source/UI/Panel.cs @@ -0,0 +1,20 @@ +using System.Numerics; +using DaggerFramework.Rendering; + +namespace DaggerFramework.UI; + +public class Panel : Container +{ + public PanelStyle Style { get; set; } + + public Panel(PanelStyle style) + { + Style = style; + } + + protected override void OnRender(Renderer renderer) + { + base.OnRender(renderer); + renderer.DrawRectangle(Rect.Size, Style.BackgroundColor); + } +} \ No newline at end of file diff --git a/DaggerFramework/Source/UI/PanelStyle.cs b/DaggerFramework/Source/UI/PanelStyle.cs new file mode 100644 index 0000000..01e2d21 --- /dev/null +++ b/DaggerFramework/Source/UI/PanelStyle.cs @@ -0,0 +1,6 @@ +namespace DaggerFramework.UI; + +public struct PanelStyle +{ + public Color BackgroundColor { get; set; } +} \ No newline at end of file diff --git a/DaggerFramework/Source/UI/Rect.cs b/DaggerFramework/Source/UI/Rect.cs new file mode 100644 index 0000000..5885111 --- /dev/null +++ b/DaggerFramework/Source/UI/Rect.cs @@ -0,0 +1,10 @@ +using System.Numerics; + +namespace DaggerFramework.UI; + +public class Rect +{ + public Vector2 Position { get; set; } + public Vector2 Size { get; set; } + public Vector2 Scale { get; set; } +} \ No newline at end of file diff --git a/DaggerFramework/Source/UI/TextLabel.cs b/DaggerFramework/Source/UI/TextLabel.cs new file mode 100644 index 0000000..5a139a7 --- /dev/null +++ b/DaggerFramework/Source/UI/TextLabel.cs @@ -0,0 +1,39 @@ +using DaggerFramework.Rendering; + +namespace DaggerFramework.UI; + +public class TextLabel : UIElement +{ + public string Text { get; set; } = string.Empty; + public Font Font + { + get => _font; set + { + _isDirty = true; + _font = value; + } + } + public int FontSize { get; set; } = 16; + public Color FontColor { get; set; } = Color.White; + protected override void OnRender(Renderer renderer) + { + if (_isDirty && _font != null) + { + _fontHandle = renderer.LoadFont(_font); + _isDirty = false; + } + + if (_font == null) + { + renderer.DrawDebugText(Text, FontSize, FontColor); + } + else + { + renderer.DrawText(_fontHandle, Text, FontSize, FontColor); + } + } + + private Font? _font; + private int _fontHandle; + private bool _isDirty; +} \ No newline at end of file diff --git a/DaggerFramework/Source/UI/UIElement.cs b/DaggerFramework/Source/UI/UIElement.cs new file mode 100644 index 0000000..96a8344 --- /dev/null +++ b/DaggerFramework/Source/UI/UIElement.cs @@ -0,0 +1,54 @@ +using System.Numerics; +using DaggerFramework.Rendering; +using DaggerFramework.Utils; + +namespace DaggerFramework.UI; + +public abstract class UIElement +{ + public Rect Rect { get; set; } = new Rect(); + public SizeFlags VerticalSizeFlags { get; set; } = SizeFlags.Fill; + public SizeFlags HorizontalSizeFlags { get; set; } = SizeFlags.Fill; + + public Vector2 ExpandRatio { get; set; } = Vector2.One; + + public UIElement() + { + children = new(); + } + + public void AddChild(UIElement child) + { + children.Add(child); + child.parent = this; + } + + public void Render(Renderer renderer) + { + renderer.SetTransform(Rect.Position, Vector2.Zero, 0); + OnRender(renderer); + + foreach (UIElement child in children) + { + renderer.SetTransform(child.Rect.Position, Vector2.Zero, 0); + child.Render(renderer); + } + } + + protected abstract void OnRender(Renderer renderer); + + protected List children; + protected UIElement? parent; + + private Logger _logger = new(nameof(UIElement)); +} + + +[Flags] +public enum SizeFlags +{ + ShrinkBegin, + ShrinkCenter, + ShrinkEnd, + Fill +} \ No newline at end of file diff --git a/DaggerFramework/Source/UI/VerticalPanel.cs b/DaggerFramework/Source/UI/VerticalPanel.cs new file mode 100644 index 0000000..2058f0e --- /dev/null +++ b/DaggerFramework/Source/UI/VerticalPanel.cs @@ -0,0 +1,22 @@ +using System.Numerics; + +namespace DaggerFramework.UI; + +public class VerticalPanel : Panel +{ + public float Spacing { get; set; } = 16; + public VerticalPanel(PanelStyle style) : base(style) + { + } + + protected override void RearrangeChild(int idx, UIElement child) + { + base.RearrangeChild(idx, child); + + var yOffset = idx * Spacing; + var rect = child.Rect; + + rect.Position = Rect.Position; + rect.Position = new Vector2(rect.Position.X, yOffset); + } +} \ No newline at end of file diff --git a/TestGame/TestGame.cs b/TestGame/TestGame.cs index d92ba2f..6e08a76 100644 --- a/TestGame/TestGame.cs +++ b/TestGame/TestGame.cs @@ -20,7 +20,8 @@ public class TestGame : Game _renderer.CreateAndInitialize(new WindowSettings() { Title = "Test Game", - Size = new Vector2(1280, 720) + Size = new Vector2(1280, 720), + Resizable = true, }, new RendererSettings() { UseVSync = true @@ -73,25 +74,6 @@ public class TestGame : Game { while (!_scene.ShouldStop()) { - // _renderer.BeginFrame(); - // _renderer.ClearBackground(Color.Black); - - // if (_inputHandler.IsActionJustPressed("play")) - // { - // var instance = _audioBackend.CreateInstance(_testSound) - // .PitchVariation(min: 0.9f, max: 1.2f) - // .VolumeVariation(min: 0.90f, max: 1.0f); - // instance.Play(); - // } - - // _audioBackend.Update(); - - // _renderer.SetTransform(new Vector2(32, 32)); - // _renderer.DrawCircle(16f, Color.Chocolate); - - // _renderer.DrawText(_fontHandle, $"{(int)(1 / _renderer.GetFrameTime())} FPS", 20, Color.White); - - // _renderer.EndFrame(); _scene.Update(); } } diff --git a/TestGame/UiLayer.cs b/TestGame/UiLayer.cs index 2f162b2..58e8718 100644 --- a/TestGame/UiLayer.cs +++ b/TestGame/UiLayer.cs @@ -1,34 +1,80 @@ using System.Numerics; using DaggerFramework; +using DaggerFramework.Rendering; using DaggerFramework.SceneGraph; +using DaggerFramework.UI; +using DaggerFramework.Utils; -public class UiLayer : EntityLayer +public class UiLayer : Layer { protected override void OnStart() { base.OnStart(); GetResources(); - CreateAndAddEntities(); + CreateUiElements(); } protected override void OnUpdate(double dt) { base.OnUpdate(dt); - - _fpsText.Text = $"{MathF.Round(1 / (float)dt)} FPS"; + // _textLabel.Text = $"{MathF.Round(1 / (float)dt)} FPS"; + _screenContainer.UpdateRect(Vector2.Zero, Scene.Renderer.WindowSize); } - private void CreateAndAddEntities() + protected override void OnBeginDraw(Renderer renderer) { - _fpsText = new Text2d() + + } + + protected override void OnDraw(Renderer renderer) + { + _screenContainer.Render(renderer); + } + + protected override void OnEndDraw(Renderer renderer) + { + + } + + private void CreateUiElements() + { + _screenContainer = new Container(); + _screenContainer.UpdateRect(Vector2.Zero, Scene.Renderer.WindowSize); + + var style = new PanelStyle() { - Font = _defaultFont, - Position = Vector2.One * 16, - FontSize = 20 + BackgroundColor = new Color(0.25f, 0.25f, 0.25f, 1.0f) }; - AddEntity(_fpsText); + _panel = new MarginPanel(style) + { + ExpandRatio = new Vector2(0.5f, 1.0f), + RelativeMargin = Vector2.One * 0.01f + }; + _screenContainer.AddChild(_panel); + + var exampleText = new TextLabel() + { + Font = _defaultFont, + FontSize = 30, + Text = "This Panel will occupy 50% of the screen.\nHow cool is that?" + }; + + _panel.AddChild(exampleText); + + // var verticalPanel = new VerticalPanel(new PanelStyle() + // { + // BackgroundColor = Color.White, + // }); + + // verticalPanel.ExpandRatio = new Vector2(1f, 0.5f); + + // _panel.AddChild(verticalPanel); + + // verticalPanel.AddChild(new Panel(new PanelStyle() { BackgroundColor = Color.Red })); + // verticalPanel.AddChild(new Panel(new PanelStyle() { BackgroundColor = Color.Green })); + // verticalPanel.AddChild(new Panel(new PanelStyle() { BackgroundColor = Color.Blue })); } private void GetResources() @@ -36,6 +82,11 @@ public class UiLayer : EntityLayer ResourceManager.TryGetResource("inter_regular", out _defaultFont); } - private Text2d _fpsText; + private Font _defaultFont; + private Container _screenContainer; + private Panel _panel, _contentPanel; + private TextLabel _textLabel; + + private Logger _logger = new(nameof(UiLayer)); } \ No newline at end of file