From f7af843d6f0f85e04d1a9b2e3f353ea2f37b9692 Mon Sep 17 00:00:00 2001 From: JacobTech Date: Thu, 5 Jan 2023 21:42:02 -0500 Subject: [PATCH] Context Menu --- GraphicsManager/ContextMenu.cs | 86 +++++++++++++++++++++ GraphicsManager/GraphicsManager.csproj | 2 +- GraphicsManager/Interfaces/IRenderObject.cs | 1 + GraphicsManager/Objects/Core/Texture.cs | 60 ++++++++++++-- GraphicsManager/Objects/Core/Uniform.cs | 16 ---- GraphicsManager/Objects/Core/Uniforms.cs | 16 ---- GraphicsManager/Objects/FlowLayout.cs | 1 + GraphicsManager/Objects/Label.cs | 35 +++++---- GraphicsManager/Objects/Rectangle.cs | 11 ++- GraphicsManager/Objects/RoundedButton.cs | 1 + GraphicsManager/Objects/RoundedRectangle.cs | 8 +- GraphicsManager/Objects/Textbox.cs | 1 + GraphicsManager/Objects/UserControl.cs | 1 + GraphicsManager/Window.cs | 8 ++ 14 files changed, 187 insertions(+), 60 deletions(-) create mode 100644 GraphicsManager/ContextMenu.cs delete mode 100755 GraphicsManager/Objects/Core/Uniform.cs delete mode 100755 GraphicsManager/Objects/Core/Uniforms.cs diff --git a/GraphicsManager/ContextMenu.cs b/GraphicsManager/ContextMenu.cs new file mode 100644 index 0000000..7649d1e --- /dev/null +++ b/GraphicsManager/ContextMenu.cs @@ -0,0 +1,86 @@ +using GraphicsManager.Enums; +using GraphicsManager.Interfaces; +using GraphicsManager.Objects; +using GraphicsManager.Objects.Core; +using OpenTK.Windowing.Desktop; +using OpenTK.Windowing.Common; +using OpenTK.Graphics.OpenGL4; +using OpenTK.Windowing.GraphicsLibraryFramework; + +namespace GraphicsManager; + +public class ContextMenu : Window +{ + private static NativeWindowSettings set = new() + { + Title = nameof(ContextMenu), + WindowBorder = WindowBorder.Hidden, + APIVersion = new Version(3, 2), + StartFocused = false, + Size = new OpenTK.Mathematics.Vector2i(400, 5), + StartVisible = false, + }; + + private FlowLayout fl; + + public ControlList Items => ((FlowLayout)(Controls[0])).Controls; + + public event Func? OnItemClick; + + public ContextMenu(int Width) : base(set) + { + this.Size = new(Width, 5); + Controls.Add(fl = new FlowLayout(){Size = new(Width,5), Anchor = ObjectAnchor.All}); + Items.ControlAdded += ItemsOnControlAdded; + BackgroundColor = new(0, 0, 0, 0); + } + + private Task ItemsOnControlAdded(IRenderObject arg) + { + arg.Clicked += ArgOnClicked; + this.Context.MakeCurrent(); + fl.Size = new(this.Size.X, arg.Location.Y + arg.Size.Y); + this.Size = fl.Size; + GL.Viewport(0,0, this.Size.X, this.Size.Y); + return Task.CompletedTask; + } + + protected override void OnResize(ResizeEventArgs e) + { + + } + + public void HideContext(Window Parent) + { + if (Parent.ActiveMenu != this) return; + Parent.ActiveMenu = null; + Context.MakeCurrent(); + IsVisible = false; + } + + public void ShowContext(Window Parent) + { + if (Parent.ActiveMenu == this) + { + Location = new((int)Parent.Location.X + (int)Parent.MousePosition.X, (int)Parent.Location.Y + (int)Parent.MousePosition.Y); + Focus(); + return; + } + if (Parent.ActiveMenu is not null) + { + Parent.ActiveMenu.HideContext(Parent); + } + Parent.ActiveMenu = this; + Context.MakeCurrent(); + Location = new((int)Parent.Location.X + (int)Parent.MousePosition.X, (int)Parent.Location.Y + (int)Parent.MousePosition.Y); + IsVisible = true; + GL.Viewport(0, 0, this.Size.X, this.Size.Y); + DrawFrame(); + } + + private Task ArgOnClicked(IRenderObject arg) + { + if (OnItemClick is not null) _ = OnItemClick.Invoke(arg); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/GraphicsManager/GraphicsManager.csproj b/GraphicsManager/GraphicsManager.csproj index 2a12cfe..0280f25 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-alpha999999999992 + 1.0.0-alpha99999999999996 diff --git a/GraphicsManager/Interfaces/IRenderObject.cs b/GraphicsManager/Interfaces/IRenderObject.cs index f02efc7..5e29c0d 100755 --- a/GraphicsManager/Interfaces/IRenderObject.cs +++ b/GraphicsManager/Interfaces/IRenderObject.cs @@ -5,6 +5,7 @@ namespace GraphicsManager.Interfaces; public interface IRenderObject { + public ContextMenu? ContextMenu { get; set; } public ObjectAnchor Anchor { get; set; } public bool Loaded { get; } public void LoadToParent(IParent Parent, Window Window); diff --git a/GraphicsManager/Objects/Core/Texture.cs b/GraphicsManager/Objects/Core/Texture.cs index cbd43db..1421cdc 100755 --- a/GraphicsManager/Objects/Core/Texture.cs +++ b/GraphicsManager/Objects/Core/Texture.cs @@ -1,6 +1,7 @@ using GraphicsManager.Structs; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; +using OpenTK.Windowing.Desktop; using SharpFont; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; @@ -11,7 +12,7 @@ namespace GraphicsManager.Objects.Core; public class Texture { - public static readonly Shader TextureShader = new("RectangleTexture", true); + public static readonly Dictionary TextureShader = new (); public int handel; public Texture(byte[] File) @@ -45,16 +46,63 @@ public class Texture { } - internal static Texture TextureForChar(Font l, char charter, Face[] faces) + internal static Character GetChar(Font l, char charter, Face[] faces) + { + Character t = new(); + for (int i = 0; i < faces.Length; i++) + { + try + { +try +{ + faces[i].SetPixelSizes(0, l.PixelHeight); +} +catch (Exception e) +{ + continue; +} + faces[i].SelectCharmap(Encoding.Unicode); + ushort temp = ((ushort)charter); + if (faces[i].GetCharIndex(temp) == 0) continue; + faces[i].LoadChar(temp, LoadFlags.Render, LoadTarget.Normal); + GlyphSlot glyph = faces[i].Glyph; + FTBitmap bitmap = glyph.Bitmap; + + t = new() + { + Size = new Vector2(bitmap.Width, bitmap.Rows), + Bearing = new Vector2(glyph.BitmapLeft, glyph.BitmapTop), + Advance = (int)glyph.Advance.X.Value, + }; + } + catch (Exception ex) + { + Console.WriteLine(ex); + continue; + } + } + + return t; + } + + internal static Texture TextureForChar(IGLFWGraphicsContext con, Font l, char charter, Face[] faces) { Texture t = new(); for (int i = 0; i < faces.Length; i++) { try { - if (!Label._characters.ContainsKey(l)) Label._characters.Add(l, new Dictionary()); - if (Label._characters[l].ContainsKey(charter)) return Label._characters[l][(ushort)charter].Texture; - faces[i].SetPixelSizes(0, l.PixelHeight); + if (!Label._characters[con].ContainsKey(l)) Label._characters[con].Add(l, new Dictionary()); + if (Label._characters[con][l].ContainsKey(charter)) return Label._characters[con][l][(ushort)charter].Texture; + try + { + faces[i].SetPixelSizes(0, l.PixelHeight); + } + catch (Exception e) + { + continue; + } + GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); @@ -81,7 +129,7 @@ public class Texture Texture = t, }; - Label._characters[l].Add(temp, cha); + Label._characters[con][l].Add(temp, cha); } catch (Exception ex) { diff --git a/GraphicsManager/Objects/Core/Uniform.cs b/GraphicsManager/Objects/Core/Uniform.cs deleted file mode 100755 index c79aa7a..0000000 --- a/GraphicsManager/Objects/Core/Uniform.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using System.Text; -using System.Threading.Tasks; -using OpenTK.Mathematics; -using Vector4 = OpenTK.Mathematics.Vector4; - -namespace GraphicsManager.Objects.Core; - -public record Uniform where TVertex : struct -{ - public int Location { get; set; } - public TVertex Value { get; set; } -} diff --git a/GraphicsManager/Objects/Core/Uniforms.cs b/GraphicsManager/Objects/Core/Uniforms.cs deleted file mode 100755 index 210581b..0000000 --- a/GraphicsManager/Objects/Core/Uniforms.cs +++ /dev/null @@ -1,16 +0,0 @@ -using OpenTK.Mathematics; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace GraphicsManager.Objects.Core; - -public class Uniforms -{ - public List> Uniform4 { get; set; } = new(); - public List> Uniform3 { get; set; } = new(); - public List> Uniform2 { get; set; } = new(); - public List> Uniform1 { get; set; } = new(); -} diff --git a/GraphicsManager/Objects/FlowLayout.cs b/GraphicsManager/Objects/FlowLayout.cs index b0b762d..f23cec7 100644 --- a/GraphicsManager/Objects/FlowLayout.cs +++ b/GraphicsManager/Objects/FlowLayout.cs @@ -159,6 +159,7 @@ public class FlowLayout : IRenderObject, IParent private MouseWheelEventArgs dis; Timer t; private Queue scrols = new(); + public ContextMenu? ContextMenu { get => _bounds.ContextMenu; set => _bounds.ContextMenu = value; } public void TryDraw() { diff --git a/GraphicsManager/Objects/Label.cs b/GraphicsManager/Objects/Label.cs index 8dda3ba..9ace535 100755 --- a/GraphicsManager/Objects/Label.cs +++ b/GraphicsManager/Objects/Label.cs @@ -5,6 +5,7 @@ using GraphicsManager.Structs; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; using OpenTK.Windowing.Common; +using OpenTK.Windowing.Desktop; using OpenTK.Windowing.GraphicsLibraryFramework; using SharpFont; using Encoding = SharpFont.Encoding; @@ -13,8 +14,9 @@ namespace GraphicsManager.Objects; public class Label : IRenderObject { - public static readonly Shader DefaultTextShader = new("Label", true); + public static readonly Dictionary DefaultTextShader = new(); public static readonly Font DefaultFont = new(); + public ContextMenu? ContextMenu { get; set; } = null; public IParent? Parent { get; private set; } public ObjectAnchor Anchor { get; set; } = ObjectAnchor.Left | ObjectAnchor.Top; private Vector2 laf = new(), saf = new(); @@ -43,7 +45,7 @@ public class Label : IRenderObject } } - public static readonly Dictionary> _characters = new(); + public static readonly Dictionary>> _characters = new(); private string text = string.Empty; public int VAO { get; private set; } public int VBO { get; private set; } @@ -55,7 +57,6 @@ public class Label : IRenderObject { if (value is null) value = string.Empty; text = value; - if (!_characters.ContainsKey(Font)) _characters.Add(Font, new Dictionary()); float addy = Font.PixelHeight * Scale, addx = 0F, char_x = 0F, hhh = 0F; for (int i = 0; i < value.Length; i++) { @@ -64,20 +65,16 @@ public class Label : IRenderObject character = value[i]; else character = PasswordChar.Value; - 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; + Character cha = Texture.GetChar(Font, character, Font.Faces.ToArray()); + float w = cha.Size.X * Scale; + float xrel = char_x + cha.Bearing.X * Scale; if (character == '\n') { hhh += Font.PixelHeight; char_x = 0f; addy += Font.PixelHeight * Scale; } - char_x += (_characters[Font][character].Advance >> 6) * Scale; + char_x += (cha.Advance >> 6) * Scale; if (xrel + w > addx) addx = xrel + w; } @@ -89,7 +86,7 @@ public class Label : IRenderObject } } } - public Shader Shader { get; set; } = DefaultTextShader; + public Shader Shader { get; set; } = null!; public Font Font { get; set; } = DefaultFont; public float Scale { get; set; } = 1.0f; public Color4 Color { get; set; } = new Color4(255, 255, 255, 255); @@ -146,8 +143,12 @@ public class Label : IRenderObject c = Text[i]; else c = PasswordChar.Value; - if (!_characters[Font].ContainsKey(c)) break; - Character ch = _characters[Font][c]; + if (!_characters[Window!.Context][Font].ContainsKey(c)) + { + var f = Texture.TextureForChar(Window!.Context, Font, c, Font.Faces.ToArray()); + f.LoadText(); + } + Character ch = _characters[Window!.Context][Font][c]; int maxx = 0; int maxy = (int)Font.PixelHeight; if (c == '\n') @@ -185,7 +186,9 @@ public class Label : IRenderObject public void LoadToParent(IParent window, Window win) { if (Loaded) return; - if (!_characters.ContainsKey(Font)) _characters.Add(Font, new Dictionary()); + if (!_characters.ContainsKey(win!.Context)) _characters.Add(win!.Context, new()); + if (!_characters[win!.Context].ContainsKey(Font)) _characters[win!.Context].Add(Font, new Dictionary()); + if (Shader is null) Shader = DefaultTextShader[win.Context]; Parent = window; Window = win; Window.MouseMove += WindowOnMouseMove; @@ -226,6 +229,8 @@ public class Label : IRenderObject private void WindowOnMouseDown(MouseButtonEventArgs obj) { if (mouseinside && obj.Button == MouseButton.Button1 && Clicked is not null) _ = Clicked.Invoke(this); + if (mouseinside && obj.Button == MouseButton.Button2 && ContextMenu is not null) ContextMenu.ShowContext(Window!); + if (!mouseinside && ContextMenu is not null) ContextMenu.HideContext(Window!); } private bool mouseinside = false; diff --git a/GraphicsManager/Objects/Rectangle.cs b/GraphicsManager/Objects/Rectangle.cs index 88f6a64..647f41e 100755 --- a/GraphicsManager/Objects/Rectangle.cs +++ b/GraphicsManager/Objects/Rectangle.cs @@ -4,17 +4,19 @@ using GraphicsManager.Objects.Core; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; using OpenTK.Windowing.Common; +using OpenTK.Windowing.Desktop; using OpenTK.Windowing.GraphicsLibraryFramework; namespace GraphicsManager.Objects; public class Rectangle : ITextureObject { - public static readonly Shader DefaultShader = new("Rectangle", true); + public static readonly Dictionary DefaultShader = new(); public ObjectAnchor Anchor { get; set; } = ObjectAnchor.Left | ObjectAnchor.Top; public Texture? Texture { get; private set; } + public ContextMenu? ContextMenu { get; set; } = null; public Rectangle(Texture? texture = null) { @@ -78,6 +80,7 @@ public class Rectangle : ITextureObject if (Loaded) return; this.Parent = Parent; this.Window = Window; + if (Shader is null) Shader = DefaultShader[Window.Context]; int pos = Points.Length - 3; if (Texture is not null) pos -= 2; pos = 4; @@ -92,7 +95,7 @@ public class Rectangle : ITextureObject GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, add * sizeof(float), 0); if (Texture is not null) { - Shader = Texture.TextureShader; + Shader = Texture.TextureShader[Window.Context]; Texture.Load(Shader.GetAttribLocation("aTexCoord")); } GL.EnableVertexAttribArray(0); @@ -134,6 +137,8 @@ public class Rectangle : ITextureObject private void Window_MouseDown(OpenTK.Windowing.Common.MouseButtonEventArgs e) { if (mouseinside && e.Button == MouseButton.Button1 && Clicked is not null) _ = Clicked.Invoke(this); + if (mouseinside && e.Button == MouseButton.Button2 && ContextMenu is not null) ContextMenu.ShowContext(Window!); + if (!mouseinside && ContextMenu is not null) ContextMenu.HideContext(Window!); } ~Rectangle() @@ -144,7 +149,7 @@ public class Rectangle : ITextureObject GL.DeleteVertexArray(ArrayObject); } - public Shader Shader { get; set; } = DefaultShader; + public Shader Shader { get; set; } = null; public int ElementBufferObject { get; private set; } public int BufferObject { get; private set; } public int ArrayObject { get; private set; } diff --git a/GraphicsManager/Objects/RoundedButton.cs b/GraphicsManager/Objects/RoundedButton.cs index cf300c9..38a230d 100755 --- a/GraphicsManager/Objects/RoundedButton.cs +++ b/GraphicsManager/Objects/RoundedButton.cs @@ -43,6 +43,7 @@ public class RoundedButton : IRenderObject 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 ContextMenu? ContextMenu { get => _bounds.ContextMenu; set => _bounds.ContextMenu = value; } public Vector2i Size { get diff --git a/GraphicsManager/Objects/RoundedRectangle.cs b/GraphicsManager/Objects/RoundedRectangle.cs index 2b592bc..996290f 100755 --- a/GraphicsManager/Objects/RoundedRectangle.cs +++ b/GraphicsManager/Objects/RoundedRectangle.cs @@ -11,9 +11,8 @@ namespace GraphicsManager.Objects; public class RoundedRectangle : IRenderObject { - public static readonly Shader DefaultShader = Rectangle.DefaultShader; - public ObjectAnchor Anchor { get; set; } = ObjectAnchor.Left | ObjectAnchor.Top; + public ContextMenu? ContextMenu { get; set; } = null; private const int sn = 4, r = 5; private int sn_ = sn, r_ = r; @@ -131,6 +130,7 @@ public class RoundedRectangle : IRenderObject if (Loaded) return; this.Parent = Parent; this.Window = Window; + if (Shader is null) Shader = Rectangle.DefaultShader[Window.Context]; int pos = Points.Length - 3; pos = 4; @@ -179,6 +179,8 @@ public class RoundedRectangle : IRenderObject private void Window_MouseDown(OpenTK.Windowing.Common.MouseButtonEventArgs e) { if (mouseinside && e.Button == MouseButton.Button1 && Clicked is not null) _ = Clicked.Invoke(this); + if (mouseinside && e.Button == MouseButton.Button2 && ContextMenu is not null) ContextMenu.ShowContext(Window!); + if (!mouseinside && ContextMenu is not null) ContextMenu.HideContext(Window!); } ~RoundedRectangle() @@ -187,7 +189,7 @@ public class RoundedRectangle : IRenderObject GL.DeleteBuffer(BufferObject); } - public Shader Shader { get; set; } = DefaultShader; + public Shader Shader { get; set; } = null!; public int ElementBufferObject { get; private set; } public int BufferObject { get; private set; } public int ArrayObject { get; private set; } diff --git a/GraphicsManager/Objects/Textbox.cs b/GraphicsManager/Objects/Textbox.cs index 8336054..b0aae1f 100755 --- a/GraphicsManager/Objects/Textbox.cs +++ b/GraphicsManager/Objects/Textbox.cs @@ -11,6 +11,7 @@ public class Textbox : IRenderObject { private RoundedRectangle _bounds, _inside; private Label _label; + public ContextMenu? ContextMenu { get => _bounds.ContextMenu; set => _bounds.ContextMenu = value; } public Textbox() { _bounds = new RoundedRectangle(); diff --git a/GraphicsManager/Objects/UserControl.cs b/GraphicsManager/Objects/UserControl.cs index 97ade95..7475cd2 100755 --- a/GraphicsManager/Objects/UserControl.cs +++ b/GraphicsManager/Objects/UserControl.cs @@ -77,6 +77,7 @@ public class UserControl : IRenderObject, IParent public event Func? WindowLoaded; public event Func? MouseEnter; public event Func? MouseLeave; + public ContextMenu? ContextMenu { get => _bounds.ContextMenu; set => _bounds.ContextMenu = value; } public object? Tag { get; set; } = null; public IParent? Parent { get; private set; } public Window? Window { get; private set; } diff --git a/GraphicsManager/Window.cs b/GraphicsManager/Window.cs index 6f15c74..713e9f9 100755 --- a/GraphicsManager/Window.cs +++ b/GraphicsManager/Window.cs @@ -1,6 +1,7 @@ using System.ComponentModel; using GraphicsManager.Enums; using GraphicsManager.Interfaces; +using GraphicsManager.Objects; using GraphicsManager.Objects.Core; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; @@ -21,10 +22,16 @@ public class Window : NativeWindow , IParent base.Dispose(disposing); } + internal ContextMenu? ActiveMenu { get; set; } = null; public IParent? Parent { get; } = null; public Vector2 LocationAsFloat { get; } = new Vector2(0f, 0f); public Window(NativeWindowSettings nativeWindowSettings) : base(nativeWindowSettings) { + Context.MakeCurrent(); + Texture.TextureShader.Add(Context, new("RectangleTexture", true)); + Objects.Rectangle.DefaultShader.Add(Context, new("Rectangle", true)); + Label.DefaultTextShader.Add(Context, new("Label", true)); + Label._characters.Add(Context, new()); } public Window() : base(new NativeWindowSettings()) @@ -219,6 +226,7 @@ public class Window : NativeWindow , IParent public void DrawFrame() { + Context.MakeCurrent(); frame++; Console.WriteLine($"Drawing Frame: {frame}"); GL.ClearColor(BackgroundColor.R, BackgroundColor.G, BackgroundColor.B, (BackgroundColor.A * -1) + 1);