From 38e418e3c6df717a59418bdbee5ae961dc51d357 Mon Sep 17 00:00:00 2001 From: JacobTech Date: Mon, 2 Jan 2023 23:15:41 -0500 Subject: [PATCH] I got carried away --- GraphicsManager/GraphicsManager.csproj | 2 +- GraphicsManager/Interfaces/IParent.cs | 5 +- GraphicsManager/Interfaces/IRenderObject.cs | 4 + GraphicsManager/Objects/Core/ControlList.cs | 34 +++ GraphicsManager/Objects/FlowLayout.cs | 290 ++++++++++++++++++++ GraphicsManager/Objects/Label.cs | 43 ++- GraphicsManager/Objects/Rectangle.cs | 11 +- GraphicsManager/Objects/RoundedButton.cs | 137 +++++++++ GraphicsManager/Objects/RoundedRectangle.cs | 23 +- GraphicsManager/Objects/Textbox.cs | 9 +- GraphicsManager/Objects/UserControl.cs | 87 +++--- GraphicsManager/Window.cs | 83 ++++-- 12 files changed, 644 insertions(+), 84 deletions(-) create mode 100644 GraphicsManager/Objects/Core/ControlList.cs create mode 100644 GraphicsManager/Objects/FlowLayout.cs create mode 100755 GraphicsManager/Objects/RoundedButton.cs diff --git a/GraphicsManager/GraphicsManager.csproj b/GraphicsManager/GraphicsManager.csproj index 50771e6..3f37cf3 100644 --- a/GraphicsManager/GraphicsManager.csproj +++ b/GraphicsManager/GraphicsManager.csproj @@ -10,7 +10,7 @@ False https://git.jacobtech.com/JacobTech.com/GraphicsManager git - 1.0.0-alpha8 + 1.0.0-alpha999991 diff --git a/GraphicsManager/Interfaces/IParent.cs b/GraphicsManager/Interfaces/IParent.cs index 89276ac..062ea74 100755 --- a/GraphicsManager/Interfaces/IParent.cs +++ b/GraphicsManager/Interfaces/IParent.cs @@ -10,8 +10,9 @@ public interface IParent public Vector2i Size { get; } public void ParentResize(ResizeEventArgs e); public float[] RctToFloat(int x, int y, int Width, int Height, bool hastexture = false, float z = 0.0f); - public Vector3 PointToVector(int x, int y, float z = 0.0f); - public float IntToFloat(int p, bool Invert = false); + public Vector3 PointToVector(float x, float y, float z = 0.0f); + public float IntToFloat(float p, bool Invert = false); + public void TryDraw(); public float FloatToInt(float p, bool Invert = false); public event Action MouseDown; public event Action KeyDown; diff --git a/GraphicsManager/Interfaces/IRenderObject.cs b/GraphicsManager/Interfaces/IRenderObject.cs index 310e380..f02efc7 100755 --- a/GraphicsManager/Interfaces/IRenderObject.cs +++ b/GraphicsManager/Interfaces/IRenderObject.cs @@ -18,6 +18,10 @@ public interface IRenderObject public IParent? Parent { get; } public Window? Window { get; } public bool Visible { get; set; } + public object? Tag { get; set; } public event Func? Clicked; + public event Func? MouseLeave; + public event Func? MouseEnter; + public event Func? WindowLoaded; } diff --git a/GraphicsManager/Objects/Core/ControlList.cs b/GraphicsManager/Objects/Core/ControlList.cs new file mode 100644 index 0000000..e760ada --- /dev/null +++ b/GraphicsManager/Objects/Core/ControlList.cs @@ -0,0 +1,34 @@ +using GraphicsManager.Interfaces; + +namespace GraphicsManager.Objects.Core; + +public class ControlList +{ + private List _internal = new(); + + public IRenderObject this[int Index] => _internal[Index]; + + public IEnumerable Where(Func func) => _internal.Where(func); + + public int Length => _internal.Count; + + public void Remove(IRenderObject item) + { + _internal.Remove(item); + item.Clean(); + } + + public void Add(IRenderObject item) + { + _internal.Add(item); + } + + public void Clear() + { + foreach (IRenderObject con in _internal) + { + con.Clean(); + } + _internal.Clear(); + } +} \ No newline at end of file diff --git a/GraphicsManager/Objects/FlowLayout.cs b/GraphicsManager/Objects/FlowLayout.cs new file mode 100644 index 0000000..88c53d8 --- /dev/null +++ b/GraphicsManager/Objects/FlowLayout.cs @@ -0,0 +1,290 @@ +using System.Timers; +using GraphicsManager.Enums; +using GraphicsManager.Interfaces; +using GraphicsManager.Objects.Core; +using OpenTK.Mathematics; +using OpenTK.Windowing.Common; +using Timer = System.Timers.Timer; + +namespace GraphicsManager.Objects; + +public class FlowLayout : IRenderObject, IParent +{ + private Rectangle _bounds; + + public FlowLayout() + { + _bounds = new Rectangle(); + _bounds.Clicked += _bounds_Clicked; + t = new(50); + t.Enabled = true; + t.Elapsed += TOnElapsed; + t.Start(); + } + + private Task _bounds_Clicked(IRenderObject arg) + { + if (Clicked is not null) _ = Clicked.Invoke(arg); + return Task.CompletedTask; + } + + public ControlList Controls { get; } = new(); + public ObjectAnchor Anchor { get => _bounds.Anchor; set => _bounds.Anchor = value; } + public Color4 BackgroundColor + { + get + { + Uniform? u4 = _bounds.Uniforms.Uniform4.Where(u => u.Location == 0).First(); + if (u4 is null) u4 = new() { Location = 0, Value = new(1, 1, 0, 1) }; + return new Color4(u4.Value.X, u4.Value.X, u4.Value.X, u4.Value.X); + } + set + { + Uniform u4 = _bounds.Uniforms.Uniform4.Where(u => u.Location == 0).First(); + if (u4 is not null) _bounds.Uniforms.Uniform4.Remove(u4); + if (u4 is null) u4 = new() { Location = 0 }; + u4.Value = new(value.R, value.G, value.B, value.A); + _bounds.Uniforms.Uniform4.Add(u4); + } + } + public bool Visible { get => _bounds.Visible; set => _bounds.Visible = value; } + public Vector2i Size { get => _bounds.Size; set => _bounds.Size = value; } + public Vector2 SizeAsFloat { get => _bounds.SizeAsFloat; } + public Vector2i Location { get => _bounds.Location; set => _bounds.Location = value; } + public Vector2i Position => Location; + public Vector2 LocationAsFloat { get => _bounds.LocationAsFloat; } + public Vector2i Distance { get => _bounds.Distance; } + public event Func? Clicked; + public event Action MouseDown; + public event Action KeyDown; + public event Func? WindowLoaded; + public event Func? MouseEnter; + public event Func? MouseLeave; + public object? Tag { get; set; } = null; + public IParent? Parent { get; private set; } + public Window? Window { get; private set; } + public bool Loaded { get; private set; } = false; + + public Vector2 MousePosition => Window!.MousePosition; + + public void LoadToParent(IParent Parent, Window Window) + { + if (Loaded) return; + this.Parent = Parent; + this.Window = Window; + Loaded = true; + _bounds.LoadToParent(Parent, Window); + for (int i = 0; i < Controls.Length; i++) + { + Controls[i].LoadToParent(this, Window); + } + Window.MouseWheel += WindowOnMouseWheel; + if (WindowLoaded is not null) WindowLoaded.Invoke(this); + } + + private bool isrole = false; + private MouseWheelEventArgs dis; + Timer t; + private Queue scrols = new(); + + public void TryDraw() + { + if (!isrole) Parent!.TryDraw(); + } + private void WindowOnMouseWheel(MouseWheelEventArgs obj) + { + try + { + isrole = true; + dis = obj; + if (scrols.Any()) + { + for (int i = 0; i < scrols.Count; i++) + { + scrols.Dequeue().Invoke(); + } + Parent!.TryDraw(); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + + } + + public uint HScrollPixels { get; set; } = 30; + private void TOnElapsed(object? sender, ElapsedEventArgs e) + { + try + { + if (isrole) + { + scrols.Enqueue(new Action(() => + { + for (int i = 0; i < Controls.Length; i++) + { + Controls[i].Location = new((int)(Controls[i].Location.X), + (int)(Controls[i].Location.Y - (dis.OffsetY * HScrollPixels))); + } + })); + } + + isrole = false; + } + catch (Exception exception) + { + Console.WriteLine(exception); + } + } + + public void Draw() + { + if (Loaded) + { + _bounds.Draw(); + IEnumerable needload = Controls.Where(a => a.Loaded == false); + + if (needload.Any()) + { + foreach (IRenderObject Control in needload) + { + Control.LoadToParent(this, Window!); + } + } + for (int i = 0; i < Controls.Length; i++) + { + Controls[i].Draw(); + } + } + } + + public void Clean() + { + for (int i = 0; i < Controls.Length; i++) + { + Controls[i].Clean(); + } + _bounds.Clean(); + } + + public void ParentResize(ResizeEventArgs e) + { + if (e.Width == 0 && e.Height == 0) return; + for (int i = 0; i < Controls.Length; i++) + { + if (!Controls[i].Loaded) continue; + bool top = (Controls[i].Anchor & ObjectAnchor.Top) == ObjectAnchor.Top; + bool left = (Controls[i].Anchor & ObjectAnchor.Left) == ObjectAnchor.Left; + bool right = (Controls[i].Anchor & ObjectAnchor.Right) == ObjectAnchor.Right; + bool bottom = (Controls[i].Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom; + if (!top && !bottom) { Controls[i].Anchor |= ObjectAnchor.Top; top = true; } + if (!left && !right) { Controls[i].Anchor |= ObjectAnchor.Left; left = true; } + int lx = (left ? Controls[i].Location.X : Size.X - Controls[i].Distance.X - Controls[i].Size.X); + int ly = (top ? Controls[i].Location.Y : Size.Y - Controls[i].Distance.Y - Controls[i].Size.Y); + int sy = (bottom ? Size.Y - Controls[i].Distance.Y - ly : Controls[i].Size.Y); + int sx = (right ? Size.X - Controls[i].Distance.X - lx : Controls[i].Size.X); + Controls[i].Size = new(sx, sy); + Controls[i].Location = new(lx, ly); + if (Controls[i] is IParent parent) + { + parent.ParentResize(e); + } + } + } + + #region Cool Math Things + public float[] RctToFloat(int x, int y, int Width, int Height, bool hastexture = false, float z = 0.0f) + { + if (hastexture) + { + return new float[20] { + IntToFloat(x + Width), IntToFloat(y, true), z, 1.0f, 1.0f,// top r + IntToFloat(x + Width), IntToFloat(y + Height, true), z, 1.0f, 0.0f,//b r + IntToFloat(x), IntToFloat(y + Height, true), z, 0.0f, 0.0f,//bot l + IntToFloat(x), IntToFloat(y, true), z, 0.0f, 1.0f// top l + }; + } + else + { + return new float[12] { + IntToFloat(x + Width), IntToFloat(y, true), z,// top r + IntToFloat(x + Width), IntToFloat(y + Height, true), z, //b r + IntToFloat(x), IntToFloat(y + Height, true), z, //bot l + IntToFloat(x), IntToFloat(y, true), z,// top l + }; + } + } + + public Vector3 PointToVector(float x, float y, float z = 0.0f) + { + return new Vector3(IntToFloat(x), IntToFloat(y, true), z); + } + + public float IntToFloat(float p, bool Invert = false) + { + p += (Invert ? Location.Y : Location.X); + IParent? tempp = Parent; + while (tempp is not null) + { + p += (Invert ? tempp.Position.Y : tempp.Position.X); + tempp = tempp.Parent; + } + float Size = (Invert ? Window!.Size.Y : Window!.Size.X); + double half = Math.Round((double)Size / (double)2, 1); + double Per = Math.Round((double)1 / half, 15); + if (p == half) return 0.0f; + if (Invert) + { + if (p > half) return (float)(((double)(p - half) * Per) * -1); + else return (float)(1 - (p * Per)); + } + else + { + if (p > half) return (float)((double)(p - half) * Per); + else return (float)((1 - (p * Per)) * -1); + } + } + + public float FloatToInt(float p, bool Invert = false) + { + p += (Invert ? LocationAsFloat.Y : LocationAsFloat.X); + IParent? tempp = Parent; + while (tempp is not null) + { + p += (Invert ? tempp.LocationAsFloat.Y : tempp.LocationAsFloat.X); + tempp = tempp.Parent; + } + + float Size = (Invert ? Window!.Size.Y : Window!.Size.X); + double half = Math.Round((double)Size / (double)2, 15); + if (p == 0) return (int)half; + if (Invert) + { + if (p < 0) + { + p *= -1; + p++; + return (float)(half * p); + } + else + { + return (float)(half - (p * half)); + } + } + else + { + if (p < 0) + { + p *= -1; + p++; + return (float)(Size - (half * p)); + } + else + { + return (float)(p * half + half); + } + } + } + #endregion +} \ No newline at end of file diff --git a/GraphicsManager/Objects/Label.cs b/GraphicsManager/Objects/Label.cs index c55386a..797f0d3 100755 --- a/GraphicsManager/Objects/Label.cs +++ b/GraphicsManager/Objects/Label.cs @@ -36,13 +36,28 @@ public class Label : IRenderObject { GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); if (!_characters.ContainsKey(Font)) _characters.Add(Font, new Dictionary()); + float addy = Font.PixelHeight * Scale, addx = 0F, char_x = 0F, hhh = 0F; foreach (char character in value) { - if (_characters[Font].ContainsKey(character)) continue; - var f = Texture.TextureForChar(Font, character, Font.Faces.ToArray()); - f.LoadText(); + if (!_characters[Font].ContainsKey(character)) + { + var f = Texture.TextureForChar(Font, character, Font.Faces.ToArray()); + f.LoadText(); + } + float w = _characters[Font][character].Size.X * Scale; + float xrel = char_x + _characters[Font][character].Bearing.X * Scale; + if (character == '\n') + { + hhh += Font.PixelHeight; + char_x = 0f; + addy += Font.PixelHeight * Scale; + } + char_x += (_characters[Font][character].Advance >> 6) * Scale; + if (xrel + w > addx) addx = xrel + w; } - if (Window is not null && Window.CanControleUpdate && Loaded) Window.DrawFrame(); + + Size = new((int)addx, (int)addy); + if (Window is not null && Window.CanControleUpdate && Loaded) Parent!.TryDraw(); } } } @@ -63,15 +78,15 @@ public class Label : IRenderObject { loc_ = value; if (Window is null || Parent is null) return; - locc_ = new((int)Window.FloatToInt(Parent.IntToFloat(value.X)), (int)Window.FloatToInt(Parent.IntToFloat(value.Y, true), true)); - if (Window.CanControleUpdate && Loaded) Window.DrawFrame(); + locc_ = new((int)Window.FloatToInt(Parent.IntToFloat(value.X)), (int)Window.FloatToInt(Parent.IntToFloat(value.Y + (int)Font.PixelHeight, true), true)); + if (Window.CanControleUpdate && Loaded) Parent!.TryDraw(); } } public Vector2i Size { get; set; } public void Clean() { - + GL.BindBuffer(BufferTarget.ArrayBuffer, 0); } public void Draw() @@ -102,11 +117,13 @@ public class Label : IRenderObject { if (!_characters[Font].ContainsKey(c)) break; Character ch = _characters[Font][c]; - + int maxx = 0; + int maxy = (int)Font.PixelHeight; if (c == '\n') { hhh += Font.PixelHeight; char_x = 0f; + maxy += (int)Font.PixelHeight; } else { @@ -116,7 +133,7 @@ public class Label : IRenderObject float yrel = (ch.Size.Y - ch.Bearing.Y) * Scale; yrel += hhh; char_x += (ch.Advance >> 6) * Scale; - + if (xrel + w > maxx) maxx = (int)(xrel + w); Matrix4 scaleM = Matrix4.CreateScale(new Vector3(w, h, 1.0f)); Matrix4 transRelM = Matrix4.CreateTranslation(new Vector3(xrel, yrel, 0.0f)); @@ -127,6 +144,7 @@ public class Label : IRenderObject GL.DrawArrays(PrimitiveType.Triangles, 0, 6); } + } GL.Disable(EnableCap.Blend); @@ -170,10 +188,13 @@ public class Label : IRenderObject Text = Text; Location = Location; Distance = new(window.Size.X - Size.X - Location.X, window.Size.Y - Size.Y - Location.Y); + if (WindowLoaded is not null) WindowLoaded.Invoke(this); } - - public event Func? Clicked; + public event Func? WindowLoaded; + public event Func? MouseEnter; + public event Func? MouseLeave; + public object? Tag { get; set; } = null; public bool Loaded { get; private set; } = false; } diff --git a/GraphicsManager/Objects/Rectangle.cs b/GraphicsManager/Objects/Rectangle.cs index 88b60dd..4319bb6 100755 --- a/GraphicsManager/Objects/Rectangle.cs +++ b/GraphicsManager/Objects/Rectangle.cs @@ -74,6 +74,8 @@ public class Rectangle : ITextureObject { GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.DeleteBuffer(BufferObject); + GL.DeleteBuffer(ElementBufferObject); + GL.DeleteVertexArray(ArrayObject); } public void LoadToParent(IParent Parent, Window Window) @@ -109,6 +111,7 @@ public class Rectangle : ITextureObject Window.MouseDown += Window_MouseDown; Location = Location; Distance = new(Parent.Size.X - Size.X - Location.X, Parent.Size.Y - Size.Y - Location.Y); + if (WindowLoaded is not null) WindowLoaded.Invoke(this); } public IParent? Parent { get; private set; } @@ -130,6 +133,8 @@ public class Rectangle : ITextureObject { GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.DeleteBuffer(BufferObject); + GL.DeleteBuffer(ElementBufferObject); + GL.DeleteVertexArray(ArrayObject); } public Shader Shader { get; set; } = DefaultShader; @@ -163,7 +168,7 @@ public class Rectangle : ITextureObject GL.BindVertexArray(ArrayObject); GL.BindBuffer(BufferTarget.ElementArrayBuffer, ElementBufferObject); GL.BufferData(BufferTarget.ElementArrayBuffer, Indexs.Length * sizeof(uint), Indexs, Hint); - if (Window is not null && Window.CanControleUpdate && Loaded) Window.DrawFrame(); + if (Window is not null && Window.CanControleUpdate && Loaded) Parent!.TryDraw(); } } catch (AccessViolationException v) @@ -180,6 +185,10 @@ public class Rectangle : ITextureObject public event Func? Clicked; public bool Loaded { get; private set; } = false; + public event Func? WindowLoaded; + public event Func? MouseEnter; + public event Func? MouseLeave; + public object? Tag { get; set; } = null; public Vector2i Distance { get; private set; } public Vector2i Size diff --git a/GraphicsManager/Objects/RoundedButton.cs b/GraphicsManager/Objects/RoundedButton.cs new file mode 100755 index 0000000..3de1545 --- /dev/null +++ b/GraphicsManager/Objects/RoundedButton.cs @@ -0,0 +1,137 @@ +using GraphicsManager.Enums; +using GraphicsManager.Interfaces; +using GraphicsManager.Objects.Core; +using OpenTK.Mathematics; +using OpenTK.Windowing.Common; +using OpenTK.Windowing.GraphicsLibraryFramework; + +namespace GraphicsManager.Objects; + +public class RoundedButton : IRenderObject +{ + private RoundedRectangle _bounds, _inside; + private Label _label; + public RoundedButton() + { + _bounds = new RoundedRectangle(); + _inside = new RoundedRectangle(); + _label = new Label(); + } + + public event Func? WindowLoaded; + public event Func? MouseEnter; + public event Func? MouseLeave; + public object? Tag { get; set; } = null; + public int Radius { get => _bounds.Radius; set { _bounds.Radius = value; _inside.Radius = value; } } + public int Border { get; set; } = 2; + public int Smoothness { get => _bounds.Smoothness; set { _bounds.Smoothness = value; _inside.Smoothness = value; } } + public ObjectAnchor Anchor { get => _bounds.Anchor; set { _bounds.Anchor = value; _inside.Anchor = value; _label.Anchor = value; } } + public Font Font { get => _label.Font; set => _label.Font = value; } + public string Text { get => _label.Text; set => _label.Text = value; } + public bool Loaded { get; private set; } = false; + public Vector2i Size + { + get + { + return _bounds.Size; + } + set + { + _bounds.Size = value; + _inside.Size = new(value.X - (Border * 2), value.Y - (Border * 2)); + _label.Location = new( Location.X + Border + (((value.X - (Border * 2)) / 2) - (_label.Size.X / 2)), Location.Y + Border + (((value.Y - (Border * 2)) / 2) - (_label.Size.Y / 2))); + } + } + public Vector2i Location { + get => _bounds.Location; + set + { + _bounds.Location = value; + _inside.Location = new(value.X + Border, value.Y + Border); + _label.Location = new( value.X + Border + (((Size.X - (Border * 2)) / 2) - (_label.Size.X / 2)), value.Y + Border + (((Size.Y - (Border * 2)) / 2) - (_label.Size.Y / 2))); + } + } + public Vector2 SizeAsFloat { get => _bounds.SizeAsFloat; } + public Vector2 LocationAsFloat { get => _bounds.LocationAsFloat; } + public Vector2i Distance { get => _bounds.Distance; } + public IParent? Parent { get; private set; } = null; + public Window? Window { get; private set; } = null; + + public Color4 InsideColor + { + get + { + Uniform? u4 = _inside.Uniforms.Uniform4.Where(u => u.Location == 0).First(); + if (u4 is null) u4 = new() { Location = 0, Value = new(1, 1, 0, 1) }; + return new Color4(u4.Value.X, u4.Value.X, u4.Value.X, u4.Value.X); + } + set + { + Uniform u4 = _inside.Uniforms.Uniform4.Where(u => u.Location == 0).First(); + if (u4 is not null) _inside.Uniforms.Uniform4.Remove(u4); + if (u4 is null) u4 = new() { Location = 0 }; + u4.Value = new(value.R, value.G, value.B, value.A); + _inside.Uniforms.Uniform4.Add(u4); + } + } + public Color4 BorderColor + { + get + { + Uniform u4 = _bounds.Uniforms.Uniform4.Where(u => u.Location == 0).First(); + if (u4 is null) u4 = new() { Location = 0, Value = new(1, 1, 0, 1) }; + return new Color4(u4.Value.X, u4.Value.X, u4.Value.X, u4.Value.X); + } + set + { + Uniform u4 = _bounds.Uniforms.Uniform4.Where(u => u.Location == 0).First(); + if (u4 is not null) _bounds.Uniforms.Uniform4.Remove(u4); + if (u4 is null) u4 = new() { Location = 0 }; + u4.Value = new(value.R, value.G, value.B, value.A); + _bounds.Uniforms.Uniform4.Add(u4); + } + } + public bool Visible { get; set; } = true; + public event Func? Clicked; + + public void Clean() + { + _bounds.Clean(); + _inside.Clean(); + _label.Clean(); + } + + public void Draw() + { + if (!Visible || !Loaded) return; + _bounds.Draw(); + _inside.Draw(); + _label.Draw(); + } + + public void LoadToParent(IParent Parent, Window Window) + { + if (Loaded) return; + this.Parent = Parent; + this.Window = Window; + this.Window.MouseDown += Window_MouseDown; + Loaded = true; + _bounds.LoadToParent(Parent, Window); + _inside.LoadToParent(Parent, Window); + _label.LoadToParent(Parent, Window); + Location = Location; + if (WindowLoaded is not null) WindowLoaded.Invoke(this); + } + + private void Window_MouseDown(OpenTK.Windowing.Common.MouseButtonEventArgs e) + { + if (e.Button == MouseButton.Button1 && + Parent?.IntToFloat(Location.X) <= Parent?.IntToFloat((int)Parent?.MousePosition.X!) && + Parent?.IntToFloat(Size.X + Location.X) >= Parent?.IntToFloat((int)Parent?.MousePosition.X!) && + Parent?.IntToFloat(Location.Y + Size.Y, true) <= Parent?.IntToFloat((int)Parent?.MousePosition.Y!, true) && + Parent?.IntToFloat(Location.Y, true) >= Parent?.IntToFloat((int)Parent?.MousePosition.Y!, true)) + { + if (Clicked is not null) Clicked.Invoke(this); + } + } +} diff --git a/GraphicsManager/Objects/RoundedRectangle.cs b/GraphicsManager/Objects/RoundedRectangle.cs index c38f3e1..6f9d1e9 100755 --- a/GraphicsManager/Objects/RoundedRectangle.cs +++ b/GraphicsManager/Objects/RoundedRectangle.cs @@ -20,6 +20,10 @@ public class RoundedRectangle : IRenderObject { Points_ = new float[36 + (((sn - 1) * 4) * 3)]; } + public event Func? WindowLoaded; + public event Func? MouseEnter; + public event Func? MouseLeave; + public object? Tag { get; set; } = null; public Uniforms Uniforms { get; set; } = new() { Uniform4 = new() { new() { Location = 0, Value = new(0,0,0,1) } } }; public int Radius @@ -119,6 +123,8 @@ public class RoundedRectangle : IRenderObject { GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.DeleteBuffer(BufferObject); + GL.DeleteBuffer(ElementBufferObject); + GL.DeleteVertexArray(ArrayObject); } public void LoadToParent(IParent Parent, Window Window) @@ -146,6 +152,7 @@ public class RoundedRectangle : IRenderObject Window.MouseDown += Window_MouseDown; Location = Location; Distance = new(Parent.Size.X - Size.X - Location.X, Parent.Size.Y - Size.Y - Location.Y); + if (WindowLoaded is not null) WindowLoaded.Invoke(this); } public IParent? Parent { get; private set; } @@ -199,7 +206,7 @@ public class RoundedRectangle : IRenderObject GL.BindVertexArray(ArrayObject); GL.BindBuffer(BufferTarget.ElementArrayBuffer, ElementBufferObject); GL.BufferData(BufferTarget.ElementArrayBuffer, Indexs.Length * sizeof(uint), Indexs, Hint); - if (Window is not null && Window.CanControleUpdate && Loaded) Window.DrawFrame(); + if (Window is not null && Window.CanControleUpdate && Loaded) Parent!.TryDraw(); } } catch (AccessViolationException v) @@ -276,7 +283,7 @@ public class RoundedRectangle : IRenderObject Vector3 _9 = Parent.PointToVector(value.X + Radius, value.Y + Size.Y, 0); Vector3 _10 = Parent.PointToVector(value.X, value.Y + Size.Y - Radius, 0); Vector3 _11 = Parent.PointToVector(value.X, value.Y + Radius, 0); - int[] ff = new int[] + float[] ff = new float[] { value.X + Size.X - Radius, value.X + Size.X - Radius, @@ -294,14 +301,14 @@ public class RoundedRectangle : IRenderObject }; for (int j = 0; j < 4; j++) { - int start = 90 - (j * 90); + float start = 90 - (j * 90); for (int i = 0; i < Smoothness - 1; i++) { - var degpre = (rotation * (i + 1)); - var deg = start - degpre; - double y = ff[j + 4] - (Math.Sin(MathHelper.DegreesToRadians(deg)) * Radius); - double x = (Math.Cos(MathHelper.DegreesToRadians(deg)) * Radius) + ff[j]; - Vector3 tri = Parent.PointToVector((int)x, (int)y, 0f); + float degpre = (rotation * (i + 1)); + float deg = start - degpre; + float y = (float)(ff[j + 4] - (Math.Sin(MathHelper.DegreesToRadians(deg)) * Radius)); + float x = (float)(Math.Cos(MathHelper.DegreesToRadians(deg)) * Radius) + ff[j]; + Vector3 tri = Parent.PointToVector(x, y, 0f); temp.Add(tri.X); temp.Add(tri.Y); temp.Add(tri.Z); diff --git a/GraphicsManager/Objects/Textbox.cs b/GraphicsManager/Objects/Textbox.cs index 3e78d28..a0d4578 100755 --- a/GraphicsManager/Objects/Textbox.cs +++ b/GraphicsManager/Objects/Textbox.cs @@ -18,6 +18,10 @@ public class Textbox : IRenderObject _label = new Label(); } + public event Func? WindowLoaded; + public event Func? MouseEnter; + public event Func? MouseLeave; + public object? Tag { get; set; } = null; public int Radius { get => _bounds.Radius; set { _bounds.Radius = value; _inside.Radius = value; } } public int Border { get; set; } = 2; public int Smoothness { get => _bounds.Smoothness; set { _bounds.Smoothness = value; _inside.Smoothness = value; } } @@ -42,7 +46,7 @@ public class Textbox : IRenderObject set { _bounds.Location = value; - _label.Location = new(value.X + Radius + 5, value.Y + Size.Y - Radius - 5); + _label.Location = new(value.X + Border + 5, Location.Y + Border + (((Size.Y - (Radius * 2)) / 2) - (_label.Size.Y / 2))); _inside.Location = new(value.X + Border, value.Y + Border); } } @@ -56,7 +60,7 @@ public class Textbox : IRenderObject { get { - Uniform u4 = _inside.Uniforms.Uniform4.Where(u => u.Location == 0).First(); + Uniform? u4 = _inside.Uniforms.Uniform4.Where(u => u.Location == 0).First(); if (u4 is null) u4 = new() { Location = 0, Value = new(1, 1, 0, 1) }; return new Color4(u4.Value.X, u4.Value.X, u4.Value.X, u4.Value.X); } @@ -117,6 +121,7 @@ public class Textbox : IRenderObject _inside.LoadToParent(Parent, Window); _label.LoadToParent(Parent, Window); Location = Location; + if (WindowLoaded is not null) WindowLoaded.Invoke(this); } private void WindowOnTextInput(TextInputEventArgs obj) diff --git a/GraphicsManager/Objects/UserControl.cs b/GraphicsManager/Objects/UserControl.cs index 6b8cd8c..1eec56a 100755 --- a/GraphicsManager/Objects/UserControl.cs +++ b/GraphicsManager/Objects/UserControl.cs @@ -15,16 +15,37 @@ public class UserControl : IRenderObject, IParent _bounds = new Rectangle(); _bounds.Clicked += _bounds_Clicked; } + + public void TryDraw() + { + Parent!.TryDraw(); + } private Task _bounds_Clicked(IRenderObject arg) { - _ = Clicked?.Invoke(arg)!; + if (Clicked is not null) _ = Clicked.Invoke(arg); return Task.CompletedTask; } - public ICollection Controls { get; } = new List(); + public ControlList Controls { get; } = new(); public ObjectAnchor Anchor { get => _bounds.Anchor; set => _bounds.Anchor = value; } - public Uniforms Uniforms { get => _bounds.Uniforms; } + public Color4 BackgroundColor + { + get + { + Uniform? u4 = _bounds.Uniforms.Uniform4.Where(u => u.Location == 0).First(); + if (u4 is null) u4 = new() { Location = 0, Value = new(1, 1, 0, 1) }; + return new Color4(u4.Value.X, u4.Value.X, u4.Value.X, u4.Value.X); + } + set + { + Uniform u4 = _bounds.Uniforms.Uniform4.Where(u => u.Location == 0).First(); + if (u4 is not null) _bounds.Uniforms.Uniform4.Remove(u4); + if (u4 is null) u4 = new() { Location = 0 }; + u4.Value = new(value.R, value.G, value.B, value.A); + _bounds.Uniforms.Uniform4.Add(u4); + } + } public bool Visible { get => _bounds.Visible; set => _bounds.Visible = value; } public Vector2i Size { get => _bounds.Size; set => _bounds.Size = value; } public Vector2 SizeAsFloat { get => _bounds.SizeAsFloat; } @@ -35,7 +56,10 @@ public class UserControl : IRenderObject, IParent public event Func? Clicked; public event Action MouseDown; public event Action KeyDown; - + public event Func? WindowLoaded; + public event Func? MouseEnter; + public event Func? MouseLeave; + public object? Tag { get; set; } = null; public IParent? Parent { get; private set; } public Window? Window { get; private set; } public bool Loaded { get; private set; } = false; @@ -49,10 +73,11 @@ public class UserControl : IRenderObject, IParent this.Window = Window; Loaded = true; _bounds.LoadToParent(Parent, Window); - foreach (IRenderObject obj in Controls) + for (int i = 0; i < Controls.Length; i++) { - obj.LoadToParent(this, Window); + Controls[i].LoadToParent(this, Window); } + if (WindowLoaded is not null) WindowLoaded.Invoke(this); } public void Draw() @@ -69,18 +94,18 @@ public class UserControl : IRenderObject, IParent Control.LoadToParent(this, Window!); } } - foreach (IRenderObject Control in Controls) + for (int i = 0; i < Controls.Length; i++) { - Control.Draw(); + Controls[i].Draw(); } } } public void Clean() { - foreach (IRenderObject Control in Controls) + for (int i = 0; i < Controls.Length; i++) { - Control.Clean(); + Controls[i].Clean(); } _bounds.Clean(); } @@ -88,26 +113,24 @@ public class UserControl : IRenderObject, IParent public void ParentResize(ResizeEventArgs e) { if (e.Width == 0 && e.Height == 0) return; - foreach (IRenderObject Control in Controls) + for (int i = 0; i < Controls.Length; i++) { - if (Control.Loaded) + if (!Controls[i].Loaded) continue; + bool top = (Controls[i].Anchor & ObjectAnchor.Top) == ObjectAnchor.Top; + bool left = (Controls[i].Anchor & ObjectAnchor.Left) == ObjectAnchor.Left; + bool right = (Controls[i].Anchor & ObjectAnchor.Right) == ObjectAnchor.Right; + bool bottom = (Controls[i].Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom; + if (!top && !bottom) { Controls[i].Anchor |= ObjectAnchor.Top; top = true; } + if (!left && !right) { Controls[i].Anchor |= ObjectAnchor.Left; left = true; } + int lx = (left ? Controls[i].Location.X : Size.X - Controls[i].Distance.X - Controls[i].Size.X); + int ly = (top ? Controls[i].Location.Y : Size.Y - Controls[i].Distance.Y - Controls[i].Size.Y); + int sy = (bottom ? Size.Y - Controls[i].Distance.Y - ly : Controls[i].Size.Y); + int sx = (right ? Size.X - Controls[i].Distance.X - lx : Controls[i].Size.X); + Controls[i].Size = new(sx, sy); + Controls[i].Location = new(lx, ly); + if (Controls[i] is IParent parent) { - bool top = (Control.Anchor & ObjectAnchor.Top) == ObjectAnchor.Top; - bool left = (Control.Anchor & ObjectAnchor.Left) == ObjectAnchor.Left; - bool right = (Control.Anchor & ObjectAnchor.Right) == ObjectAnchor.Right; - bool bottom = (Control.Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom; - if (!top && !bottom) { Control.Anchor |= ObjectAnchor.Top; top = true; } - if (!left && !right) { Control.Anchor |= ObjectAnchor.Left; left = true; } - int lx = (left ? Control.Location.X : Size.X - Control.Distance.X - Control.Size.X); - int ly = (top ? Control.Location.Y : Size.Y - Control.Distance.Y - Control.Size.Y); - int sy = (bottom ? Size.Y - Control.Distance.Y - ly : Control.Size.Y); - int sx = (right ? Size.X - Control.Distance.X - lx : Control.Size.X); - Control.Size = new(sx, sy); - Control.Location = new(lx, ly); - if (Control is IParent parent) - { - parent.ParentResize(e); - } + parent.ParentResize(e); } } } @@ -135,12 +158,12 @@ public class UserControl : IRenderObject, IParent } } - public Vector3 PointToVector(int x, int y, float z = 0.0f) + public Vector3 PointToVector(float x, float y, float z = 0.0f) { return new Vector3(IntToFloat(x), IntToFloat(y, true), z); } - public float IntToFloat(int p, bool Invert = false) + public float IntToFloat(float p, bool Invert = false) { p += (Invert ? Location.Y : Location.X); IParent? tempp = Parent; @@ -149,7 +172,7 @@ public class UserControl : IRenderObject, IParent p += (Invert ? tempp.Position.Y : tempp.Position.X); tempp = tempp.Parent; } - int Size = (Invert ? Window!.Size.Y : Window!.Size.X); + float Size = (Invert ? Window!.Size.Y : Window!.Size.X); double half = Math.Round((double)Size / (double)2, 1); double Per = Math.Round((double)1 / half, 15); if (p == half) return 0.0f; @@ -175,7 +198,7 @@ public class UserControl : IRenderObject, IParent tempp = tempp.Parent; } - int Size = (Invert ? Window!.Size.Y : Window!.Size.X); + float Size = (Invert ? Window!.Size.Y : Window!.Size.X); double half = Math.Round((double)Size / (double)2, 15); if (p == 0) return (int)half; if (Invert) diff --git a/GraphicsManager/Window.cs b/GraphicsManager/Window.cs index fcda7f2..f573459 100755 --- a/GraphicsManager/Window.cs +++ b/GraphicsManager/Window.cs @@ -1,5 +1,7 @@ -using GraphicsManager.Enums; +using System.ComponentModel; +using GraphicsManager.Enums; using GraphicsManager.Interfaces; +using GraphicsManager.Objects.Core; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; using OpenTK.Windowing.Common; @@ -9,6 +11,16 @@ namespace GraphicsManager; public class Window : NativeWindow , IParent { + protected override void Dispose(bool disposing) + { + for (int i = 0; i < Controls.Length; i++) + { + Controls[i].Clean(); + } + Context.MakeNoneCurrent(); + base.Dispose(disposing); + } + public IParent? Parent { get; } = null; public Vector2 LocationAsFloat { get; } = new Vector2(0f, 0f); public Window(NativeWindowSettings nativeWindowSettings) : base(nativeWindowSettings) @@ -22,7 +34,7 @@ public class Window : NativeWindow , IParent public Vector2i Position { get; } = new Vector2i(0, 0); public Color4 BackgroundColor { get; set; } = new Color4(0, 0, 0, 255); - public ICollection Controls { get; } = new List(); + public ControlList Controls { get; } = new(); #region Cool Math Things public float[] RctToFloat(int x, int y, int Width, int Height, bool hastexture = false, float z = 0.0f) { @@ -46,14 +58,14 @@ public class Window : NativeWindow , IParent } } - public Vector3 PointToVector(int x, int y, float z = 0.0f) + public Vector3 PointToVector(float x, float y, float z = 0.0f) { return new Vector3(IntToFloat(x), IntToFloat(y, true), z); } - public float IntToFloat(int p, bool Invert = false) + public float IntToFloat(float p, bool Invert = false) { - int Size = (Invert ? this.Size.Y : this.Size.X); + float Size = (Invert ? this.Size.Y : this.Size.X); double half = Math.Round((double)Size / (double)2, 1); double Per = Math.Round((double)1 / half, 15); if (p == half) return 0.0f; @@ -71,7 +83,7 @@ public class Window : NativeWindow , IParent public float FloatToInt(float p, bool Invert = false) { - int Size = (Invert ? this.Size.Y : this.Size.X); + float Size = (Invert ? this.Size.Y : this.Size.X); double half = Math.Round((double)Size / (double)2, 15); if (p == 0) return (int)half; if (Invert) @@ -108,25 +120,25 @@ public class Window : NativeWindow , IParent if (e.Width == 0 && e.Height == 0) return; base.OnResize(e); GL.Viewport(0, 0, e.Width, e.Height); - foreach (IRenderObject Control in Controls) + for (int i = 0; i < Controls.Length; i++) { - if (!Control.Loaded) continue; - bool top = (Control.Anchor & ObjectAnchor.Top) == ObjectAnchor.Top; - bool left = (Control.Anchor & ObjectAnchor.Left) == ObjectAnchor.Left; - bool right = (Control.Anchor & ObjectAnchor.Right) == ObjectAnchor.Right; - bool bottom = (Control.Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom; - if (!top && !bottom) { Control.Anchor |= ObjectAnchor.Top; top = true; } - if (!left && !right) { Control.Anchor |= ObjectAnchor.Left; left = true; } - int lx = (left ? Control.Location.X : Size.X - Control.Distance.X - Control.Size.X); - int ly = (top ? Control.Location.Y : Size.Y - Control.Distance.Y - Control.Size.Y); - int sy = (bottom ? Size.Y - Control.Distance.Y - ly : Control.Size.Y); - int sx = (right ? Size.X - Control.Distance.X - lx : Control.Size.X); - Control.Size = new(sx, sy); - Control.Location = new(lx, ly); - if (Control is IParent parent) - { - parent.ParentResize(e); - } + if (!Controls[i].Loaded) continue; + bool top = (Controls[i].Anchor & ObjectAnchor.Top) == ObjectAnchor.Top; + bool left = (Controls[i].Anchor & ObjectAnchor.Left) == ObjectAnchor.Left; + bool right = (Controls[i].Anchor & ObjectAnchor.Right) == ObjectAnchor.Right; + bool bottom = (Controls[i].Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom; + if (!top && !bottom) { Controls[i].Anchor |= ObjectAnchor.Top; top = true; } + if (!left && !right) { Controls[i].Anchor |= ObjectAnchor.Left; left = true; } + int lx = (left ? Controls[i].Location.X : Size.X - Controls[i].Distance.X - Controls[i].Size.X); + int ly = (top ? Controls[i].Location.Y : Size.Y - Controls[i].Distance.Y - Controls[i].Size.Y); + int sy = (bottom ? Size.Y - Controls[i].Distance.Y - ly : Controls[i].Size.Y); + int sx = (right ? Size.X - Controls[i].Distance.X - lx : Controls[i].Size.X); + Controls[i].Size = new(sx, sy); + Controls[i].Location = new(lx, ly); + if (Controls[i] is IParent parent) + { + parent.ParentResize(e); + } } } @@ -135,17 +147,29 @@ public class Window : NativeWindow , IParent ParentResize(e); } + protected override void OnClosing(CancelEventArgs e) + { + GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + GL.BindVertexArray(0); + GL.UseProgram(0); + for (int i = 0; i < Controls.Length; i++) + { + Controls[i].Clean(); + } + base.OnClosing(e); + } public Rendertype Rendertype { get; set; } = Rendertype.ControlUpdates; internal bool CanControleUpdate { get; private set; } = true; public int FPS { get; set; } = 0; - + public event Func? WindowLoaded; public void StartRender() { Context.MakeCurrent(); ProcessEvents(); DrawFrame(); + if (WindowLoaded is not null) WindowLoaded.Invoke(this); while (Exists && IsVisible && !IsExiting) { ProcessEvents(); @@ -154,6 +178,11 @@ public class Window : NativeWindow , IParent Thread.Sleep(8); } } + + public void TryDraw() + { + DrawFrame(); + } public void DrawFrame() { @@ -169,9 +198,9 @@ public class Window : NativeWindow , IParent } GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - foreach (IRenderObject obj in Controls) + for (int i = 0; i < Controls.Length; i++) { - if (obj.Loaded) obj.Draw(); + if (Controls[i].Loaded) Controls[i].Draw(); } Context.SwapBuffers();