From 448e0f670f12154d489accda6c0400c8662e1e3d Mon Sep 17 00:00:00 2001 From: JacobTech Date: Mon, 21 Aug 2023 10:57:06 -0400 Subject: [PATCH] Bugs & Features. Mainly bug fixes with a few new shaders and controls. --- GraphicsManager/Enums/FontSize.cs | 14 + GraphicsManager/Enums/TextLocation.cs | 9 + GraphicsManager/GraphicsManager.csproj | 3 +- GraphicsManager/Interfaces/ILabel.cs | 6 + GraphicsManager/Interfaces/IParent.cs | 7 +- GraphicsManager/Interfaces/IRenderObject.cs | 7 +- GraphicsManager/Interfaces/ITextureObject.cs | 2 +- GraphicsManager/Objects/Core/ControlList.cs | 20 +- GraphicsManager/Objects/Core/Font.cs | 35 +- GraphicsManager/Objects/Core/FontFamily.cs | 136 +++++ .../Objects/Core/FontInteraction.cs | 149 ++++++ GraphicsManager/Objects/Core/Shader.cs | 11 +- GraphicsManager/Objects/Core/Texture.cs | 196 +++++-- .../Objects/Core/TextureManager.cs | 19 +- GraphicsManager/Objects/FlowLayout.cs | 111 +++- GraphicsManager/Objects/Label.cs | 106 +++- GraphicsManager/Objects/RainbowLabel.cs | 494 ++++++++++++++++++ GraphicsManager/Objects/Rectangle.cs | 116 ++-- GraphicsManager/Objects/RoundedButton.cs | 41 +- GraphicsManager/Objects/RoundedRectangle.cs | 47 +- GraphicsManager/Objects/TabControl.cs | 51 +- GraphicsManager/Objects/Textbox.cs | 122 ++++- GraphicsManager/Objects/TexturedTextBox.cs | 393 ++++++++++++++ GraphicsManager/Objects/UserControl.cs | 96 +++- .../Resources/Shaders/AlphaChannel.frag | 13 + .../Resources/Shaders/AlphaChannel.vert | 12 + .../Shaders/AlphaChannelTexture.frag | 14 + .../Shaders/AlphaChannelTexture.vert | 9 + .../Resources/Textures/Missing.png | Bin 0 -> 98 bytes GraphicsManager/Structs/Character.cs | 1 + GraphicsManager/Tools.cs | 62 ++- GraphicsManager/Window.cs | 154 +++--- 32 files changed, 2120 insertions(+), 336 deletions(-) create mode 100644 GraphicsManager/Enums/FontSize.cs create mode 100644 GraphicsManager/Enums/TextLocation.cs create mode 100644 GraphicsManager/Interfaces/ILabel.cs create mode 100644 GraphicsManager/Objects/Core/FontFamily.cs create mode 100644 GraphicsManager/Objects/Core/FontInteraction.cs create mode 100755 GraphicsManager/Objects/RainbowLabel.cs create mode 100755 GraphicsManager/Objects/TexturedTextBox.cs create mode 100755 GraphicsManager/Resources/Shaders/AlphaChannel.frag create mode 100755 GraphicsManager/Resources/Shaders/AlphaChannel.vert create mode 100755 GraphicsManager/Resources/Shaders/AlphaChannelTexture.frag create mode 100755 GraphicsManager/Resources/Shaders/AlphaChannelTexture.vert create mode 100644 GraphicsManager/Resources/Textures/Missing.png diff --git a/GraphicsManager/Enums/FontSize.cs b/GraphicsManager/Enums/FontSize.cs new file mode 100644 index 0000000..5bb8f3a --- /dev/null +++ b/GraphicsManager/Enums/FontSize.cs @@ -0,0 +1,14 @@ +namespace GraphicsManager.Enums; + +public enum FontSize : byte +{ + Thin, + ExtraLight, + Light, + Regular, + Medium, + SemiBold, + Bold, + ExtraBold, + Black, +} \ No newline at end of file diff --git a/GraphicsManager/Enums/TextLocation.cs b/GraphicsManager/Enums/TextLocation.cs new file mode 100644 index 0000000..1d51044 --- /dev/null +++ b/GraphicsManager/Enums/TextLocation.cs @@ -0,0 +1,9 @@ +namespace GraphicsManager.Enums; + +public enum TextLocation +{ + TopLeft, + PxLeft, + TrueCenterLeft, + PostiveTureCenterLeft +} \ No newline at end of file diff --git a/GraphicsManager/GraphicsManager.csproj b/GraphicsManager/GraphicsManager.csproj index efd6e32..749a9bd 100644 --- a/GraphicsManager/GraphicsManager.csproj +++ b/GraphicsManager/GraphicsManager.csproj @@ -10,7 +10,7 @@ False https://git.jacobtech.com/JacobTech.com/GraphicsManager git - 1.0.5-alpha08 + 1.0.6-alpha89 @@ -39,6 +39,7 @@ + diff --git a/GraphicsManager/Interfaces/ILabel.cs b/GraphicsManager/Interfaces/ILabel.cs new file mode 100644 index 0000000..e548576 --- /dev/null +++ b/GraphicsManager/Interfaces/ILabel.cs @@ -0,0 +1,6 @@ +namespace GraphicsManager.Interfaces; + +public interface ILabel : IRenderObject +{ + +} \ No newline at end of file diff --git a/GraphicsManager/Interfaces/IParent.cs b/GraphicsManager/Interfaces/IParent.cs index f447683..f350a99 100755 --- a/GraphicsManager/Interfaces/IParent.cs +++ b/GraphicsManager/Interfaces/IParent.cs @@ -1,14 +1,16 @@ -using OpenTK.Mathematics; +using GraphicsManager.Objects.Core; +using OpenTK.Mathematics; using OpenTK.Windowing.Common; +using OpenTK.Windowing.Common.Input; namespace GraphicsManager.Interfaces; public interface IParent { public Vector2 LocationAsFloat { get; } + public ControlList Controls { get; } public IParent? Parent { get; } public Vector2i Size { get; } - public Vector2i GetParentRelLocPoint(); 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(float x, float y, float z = 0.0f); @@ -17,4 +19,5 @@ public interface IParent public void ReportSizeUpdate(IRenderObject Control); public float FloatToInt(float p, bool Invert = false); public Vector2i Position { get; } + public MouseCursor HoverMouse { get; set; } } diff --git a/GraphicsManager/Interfaces/IRenderObject.cs b/GraphicsManager/Interfaces/IRenderObject.cs index ab8dfb1..e7957a5 100755 --- a/GraphicsManager/Interfaces/IRenderObject.cs +++ b/GraphicsManager/Interfaces/IRenderObject.cs @@ -1,15 +1,19 @@ using GraphicsManager.Enums; using OpenTK.Mathematics; +using OpenTK.Windowing.Common.Input; namespace GraphicsManager.Interfaces; public interface IRenderObject { + public void ForceDistanceUpdate(); + public void ForceDistanceUpdate(IParent parent); public ContextMenu? ContextMenu { get; set; } public ObjectAnchor Anchor { get; set; } public bool Loaded { get; } public void LoadToParent(IParent Parent, Window Window); public void Draw(int x, int y, int w, int h); + public MouseCursor HoverMouse { get; set; } public void Clean(); public void Focus(); public void UnFocus(); @@ -17,8 +21,7 @@ public interface IRenderObject public Vector2i Location { get; set; } public Vector2 SizeAsFloat { get; } public Vector2 LocationAsFloat { get; } - public Vector2i ScissorLocation { get; } - public Vector2i Distance { get; } + public Vector2i Distance { get; set; } public IParent? Parent { get; } public Window? Window { get; } public bool Visible { get; set; } diff --git a/GraphicsManager/Interfaces/ITextureObject.cs b/GraphicsManager/Interfaces/ITextureObject.cs index 4fb3848..6e72de8 100755 --- a/GraphicsManager/Interfaces/ITextureObject.cs +++ b/GraphicsManager/Interfaces/ITextureObject.cs @@ -9,5 +9,5 @@ namespace GraphicsManager.Interfaces; public interface ITextureObject : IRenderObject { - public Texture? Texture { get; } + public List Textures { get; } } diff --git a/GraphicsManager/Objects/Core/ControlList.cs b/GraphicsManager/Objects/Core/ControlList.cs index ac87a53..420f3cd 100644 --- a/GraphicsManager/Objects/Core/ControlList.cs +++ b/GraphicsManager/Objects/Core/ControlList.cs @@ -4,7 +4,7 @@ namespace GraphicsManager.Objects.Core; public class ControlList { - private List _internal = new(); + internal List _internal = new(); private bool Clearing = false; public IRenderObject this[int Index] => _internal[Index]; @@ -21,11 +21,14 @@ public class ControlList internal event Func? ControlAdded; internal event Func? ControlRemoved; - public void Remove(IRenderObject item) + public void Remove(IRenderObject item, bool purge = true) { _internal.Remove(item); - item.Clean(); - item = null!; + if (purge) + { + item.Clean(); + item = null!; + } GC.Collect(); if (ControlRemoved is not null && !Clearing) _ = ControlRemoved.Invoke(); } @@ -36,13 +39,16 @@ public class ControlList _internal.Add(item); } - public void Clear() + public void Clear(bool purge = true) { Clearing = true; for (int i = 0; i< _internal.Count; i++) { - _internal[i].Clean(); - _internal[i] = null!; + if (purge) + { + _internal[i].Clean(); + _internal[i] = null!; + } } _internal.Clear(); GC.Collect(); diff --git a/GraphicsManager/Objects/Core/Font.cs b/GraphicsManager/Objects/Core/Font.cs index 62beb56..ac4ece6 100755 --- a/GraphicsManager/Objects/Core/Font.cs +++ b/GraphicsManager/Objects/Core/Font.cs @@ -16,6 +16,7 @@ public class Font private static List AllFonts = new(); private static bool Backup = false; private static int addsystem = 0; + public static bool CanScanSystem = true; internal void AddSystemFontFace(string path) { Console.WriteLine("Added font: " + path); @@ -39,6 +40,8 @@ public class Font } } + + private Font() { Name = null!; @@ -50,7 +53,7 @@ public class Font AllMemoryFonts.Add(SHA256.HashData(Tools.GetResourceBytes("GraphicsManager.Resources.Fonts.TektonPro-Regular.otf")), new Face(lib, Tools.GetResourceBytes("GraphicsManager.Resources.Fonts.TektonPro-Regular.otf"), 0)); Backup = true; } - if (_SystemPre is null) + if (_SystemPre is null && CanScanSystem) { _SystemPre = new(); if (OperatingSystem.IsLinux()) @@ -76,6 +79,9 @@ public class Font } catch { + string folder = Environment.GetFolderPath(Environment.SpecialFolder.Fonts); + _SystemPre = new(); + Tools.AddFontsToList(ref _SystemPre, folder); } } @@ -84,25 +90,8 @@ public class Font try { string folder = Environment.GetFolderPath(Environment.SpecialFolder.Fonts); - - string GetFonts(string dir) - { - DirectoryInfo di = new(dir); - string files = ""; - foreach (FileInfo file in di.GetFiles()) - { - if (!file.FullName.EndsWith(".otf") && !file.FullName.EndsWith(".ttf")) continue; - if (files == "") files = file.FullName; - else files += Environment.NewLine + file.FullName; - } - foreach (DirectoryInfo direc in di.GetDirectories()) - { - files += GetFonts(direc.FullName); - } - return files; - } - - _SystemPre = GetFonts(folder).Split(Environment.NewLine).ToList(); + _SystemPre = new(); + Tools.AddFontsToList(ref _SystemPre, folder); } catch { @@ -156,6 +145,7 @@ public class Font //private static Font? Cache = null; private static List Caches = new(); + /* public static Font MakeFontFromSystem(uint PixelHeight = 12) { if (!Caches.Where(s => s.PixelHeight == PixelHeight).Any()) @@ -165,7 +155,7 @@ public class Font AllFonts.Add(f); } return Caches.Where(s => s.PixelHeight == PixelHeight).First(); - } + }*/ public static Font MakeFontFromFile(string Font) { _ = Font ?? throw new ArgumentNullException(nameof(Font)); @@ -193,7 +183,8 @@ public class Font } private bool HasTopFont = false; - public uint PixelHeight { get; set; } = 12; + //private uint ph = 12; + //public uint PixelHeight { get; set; } = 12; public string Name { get; private set; } = default!; public bool Embeded { get; private set; } public Assembly? Assembly { get; private set; } diff --git a/GraphicsManager/Objects/Core/FontFamily.cs b/GraphicsManager/Objects/Core/FontFamily.cs new file mode 100644 index 0000000..a26a4d8 --- /dev/null +++ b/GraphicsManager/Objects/Core/FontFamily.cs @@ -0,0 +1,136 @@ +using System.Diagnostics; +using GraphicsManager.Enums; +using SixLabors.Fonts; + +namespace GraphicsManager.Objects.Core; + +public class FontFamily +{ + private static uint index = 0; + public event Func? ReloadUI; + private FontSize fs = FontSize.Thin; + private uint ph = 12; + private bool i; + internal Dictionary> InternalFonts = new(); + internal Dictionary> InternalFontsi = new(); + internal Font Font = null!; + + + + public static Task LoadFontFamily() + { + FontFamily f = new(); + foreach (string font in Tools.GetFontList($"fc-list ':'family='{Tools.GetFamilyList("fc-list ':' family")[index]}' file")) + { + string fd = font.ToLower(); + string[] fda = fd.Split('.'); + fd = fda[fda.Length - 2]; + + void tryadd(FontSize s, bool i = false) + { + if (i) + { + if (!f.InternalFontsi.ContainsKey(s)) + f.InternalFontsi.Add(s, new(font, null)); + } + else + { + if (!f.InternalFonts.ContainsKey(s)) + f.InternalFonts.Add(s, new(font, null)); + } + } + + if (fd.EndsWith("italic")) + { + if (fd.EndsWith("thinitalic")) tryadd(FontSize.Thin, true); + else if (fd.EndsWith("extralightitalic")) tryadd(FontSize.ExtraLight, true); + else if (fd.EndsWith("lightitalic")) tryadd(FontSize.Light, true); + else if (fd.EndsWith("regularitalic")) tryadd(FontSize.Regular, true); + else if (fd.EndsWith("mediumitalic")) tryadd(FontSize.Medium, true); + else if (fd.EndsWith("semibolditalic")) tryadd(FontSize.SemiBold, true); + else if (fd.EndsWith("bolditalic")) tryadd(FontSize.Bold, true); + else if (fd.EndsWith("extrabolditalic")) tryadd(FontSize.ExtraBold, true); + else if (fd.EndsWith("blackitalic")) tryadd(FontSize.Black, true); + else tryadd(FontSize.Regular, true); + } + else + { + if (fd.EndsWith("thin")) tryadd(FontSize.Thin); + else if (fd.EndsWith("extralight")) tryadd(FontSize.ExtraLight); + else if (fd.EndsWith("light")) tryadd(FontSize.Light); + else if (fd.EndsWith("regular")) tryadd(FontSize.Regular); + else if (fd.EndsWith("medium")) tryadd(FontSize.Medium); + else if (fd.EndsWith("semibold")) tryadd(FontSize.SemiBold); + else if (fd.EndsWith("bold")) tryadd(FontSize.Bold); + else if (fd.EndsWith("extrabold")) tryadd(FontSize.ExtraBold); + else if (fd.EndsWith("black")) tryadd(FontSize.Black); + else tryadd(FontSize.Regular); + } + } + + index++; + return Task.FromResult(f); + } + + + public static Task LoadFontFamily(string Family) + { + FontFamily f = new(); + foreach (string font in Tools.GetFontList($"fc-list ':'family='{Family}' file")) + { + string fd = font.ToLower(); + string[] fda = fd.Split('.'); + fd = fda[fda.Length - 2]; + + void tryadd(FontSize s, bool i = false) + { + if (i) + { + if (!f.InternalFontsi.ContainsKey(s)) + f.InternalFontsi.Add(s, new(font, null)); + } + else + { + if (!f.InternalFonts.ContainsKey(s)) + f.InternalFonts.Add(s, new(font, null)); + } + } + + if (fd.EndsWith("italic")) + { + if (fd.EndsWith("thinitalic")) tryadd(FontSize.Thin, true); + if (fd.EndsWith("extralightitalic")) tryadd(FontSize.ExtraLight, true); + if (fd.EndsWith("lightitalic")) tryadd(FontSize.Light, true); + if (fd.EndsWith("regularitalic")) tryadd(FontSize.Regular, true); + if (fd.EndsWith("mediumitalic")) tryadd(FontSize.Medium, true); + if (fd.EndsWith("semibolditalic")) tryadd(FontSize.SemiBold, true); + if (fd.EndsWith("bolditalic")) tryadd(FontSize.Bold, true); + if (fd.EndsWith("extrabolditalic")) tryadd(FontSize.ExtraBold, true); + if (fd.EndsWith("blackitalic")) tryadd(FontSize.Black, true); + } + else + { + if (fd.EndsWith("thin")) tryadd(FontSize.Thin); + if (fd.EndsWith("extralight")) tryadd(FontSize.ExtraLight); + if (fd.EndsWith("light")) tryadd(FontSize.Light); + if (fd.EndsWith("regular")) tryadd(FontSize.Regular); + if (fd.EndsWith("medium")) tryadd(FontSize.Medium); + if (fd.EndsWith("semibold")) tryadd(FontSize.SemiBold); + if (fd.EndsWith("bold")) tryadd(FontSize.Bold); + if (fd.EndsWith("extrabold")) tryadd(FontSize.ExtraBold); + if (fd.EndsWith("black")) tryadd(FontSize.Black); + } + } + return Task.FromResult(f); + } + + public static async Task LoadFontFamily(string Dir, string Family) + { + FontFamily f = new(); + return f; + } + + private FontFamily() + { + } +} \ No newline at end of file diff --git a/GraphicsManager/Objects/Core/FontInteraction.cs b/GraphicsManager/Objects/Core/FontInteraction.cs new file mode 100644 index 0000000..335ec2c --- /dev/null +++ b/GraphicsManager/Objects/Core/FontInteraction.cs @@ -0,0 +1,149 @@ +using GraphicsManager.Enums; + +namespace GraphicsManager.Objects.Core; + +public class FontInteraction +{ + public FontFamily Family { get; private set; } + public Font CurrentFont { get; private set; } + private FontSize fs = FontSize.Thin; + private uint ph = 12; + private bool i; + private uint epx = 0; + public event Func? ReloadUI; + + public FontInteraction Clone() + { + return (FontInteraction)this.MemberwiseClone(); + } + + public static FontInteraction Load(FontFamily family) + { + FontInteraction c = new(family); + c.FontSize = FontSize.Regular; + return c; + } + private FontInteraction(FontFamily Family) + { + this.Family = Family; + } + + public uint PixelHeight + { + get => ph; + set + { + ph = value; + if (ReloadUI is not null) ReloadUI.Invoke(); + } + } + + public uint ExtraLinePixels + { + get => epx; + set + { + epx = value; + if (ReloadUI is not null) ReloadUI.Invoke(); + } + } + + public bool Italic + { + get => i; + set + { + if (i != value) + { + if (value) + { + if (Family.InternalFontsi.TryGetValue(FontSize, out Tuple? f)) + { + i = value; + if (f.Item2 is null) + { + switch (Italic) + { + case true: + Family.InternalFontsi[fs] = new(f.Item1, Font.MakeFontFromFile(Family.InternalFontsi[fs].Item1)); + break; + case false: + Family.InternalFonts[fs] = new(f.Item1, Font.MakeFontFromFile(Family.InternalFonts[fs].Item1)); + break; + } + } + + CurrentFont = (Family.InternalFontsi[fs].Item2!); + if (ReloadUI is not null) ReloadUI.Invoke(); + } + } + else + { + if (Family.InternalFonts.TryGetValue(FontSize, out Tuple? f)) + { + i = value; + if (f.Item2 is null) + { + switch (Italic) + { + case true: + Family.InternalFontsi[fs] = new(f.Item1, Font.MakeFontFromFile(Family.InternalFontsi[fs].Item1)); + break; + case false: + Family.InternalFonts[fs] = new(f.Item1, Font.MakeFontFromFile(Family.InternalFonts[fs].Item1)); + break; + } + } + CurrentFont = Family.InternalFonts[fs].Item2!; + if (ReloadUI is not null) ReloadUI.Invoke(); + } + } + //Font.PixelHeight = this.PixelHeight; + } + } + } + + private static Tuple gcl(Dictionary> thisList, FontSize thisValue, out FontSize fs) + { + Dictionary>.KeyCollection keys = thisList.Keys; + FontSize nearest = thisValue - + keys.Where(k => k <= thisValue) + .Min(k => thisValue - k); + fs = nearest; + return thisList[nearest]; + } + + public FontSize FontSize + { + get => fs; + set + { + Tuple f = Italic switch + { + true => gcl(Family.InternalFontsi, value, out fs), + false => gcl(Family.InternalFonts, value, out fs), + }; + if (f.Item2 is null) + { + switch (Italic) + { + case true: + Family.InternalFontsi[fs] = new(f.Item1, Font.MakeFontFromFile(Family.InternalFontsi[fs].Item1)); + break; + case false: + Family.InternalFonts[fs] = new(f.Item1, Font.MakeFontFromFile(Family.InternalFonts[fs].Item1)); + break; + } + } + + CurrentFont = Italic switch + { + true => Family.InternalFontsi[fs].Item2!, + false => Family.InternalFonts[fs].Item2!, + }; + //Font.PixelHeight = this.PixelHeight; + + if (ReloadUI is not null) ReloadUI.Invoke(); + } + } +} \ No newline at end of file diff --git a/GraphicsManager/Objects/Core/Shader.cs b/GraphicsManager/Objects/Core/Shader.cs index 8d79551..1547a2a 100755 --- a/GraphicsManager/Objects/Core/Shader.cs +++ b/GraphicsManager/Objects/Core/Shader.cs @@ -48,8 +48,11 @@ public class Shader : IDisposable GL.DeleteShader(VertexShader); } - public Shader(string ShaderSource, bool Embeded = false, Assembly? Assembly = null) + public bool ForTexture { get; private set; } = false; + + public Shader(string ShaderSource, bool Embeded = false, Assembly? Assembly = null, bool Texture = false) { + ForTexture = Texture; VertexShader = GL.CreateShader(ShaderType.VertexShader); string Base = "GraphicsManager.Resources.Shaders."; if (Assembly is not null) Base = string.Empty; @@ -93,6 +96,12 @@ public class Shader : IDisposable { return GL.GetAttribLocation(Handle, attribName); } + + public int GetUniformLocation(string attribName) + { + return GL.GetUniformLocation(Handle, attribName); + } + public void SetInt(string name, int value) { diff --git a/GraphicsManager/Objects/Core/Texture.cs b/GraphicsManager/Objects/Core/Texture.cs index 4f2fd0f..2fc1a99 100755 --- a/GraphicsManager/Objects/Core/Texture.cs +++ b/GraphicsManager/Objects/Core/Texture.cs @@ -1,10 +1,16 @@ -using GraphicsManager.Globals; -using GraphicsManager.Structs; -using OpenTK.Graphics.ES30; +using GraphicsManager.Structs; using OpenTK.Mathematics; using OpenTK.Windowing.Desktop; using SharpFont; using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.Formats.Gif; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Formats.Pbm; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.Formats.Tga; +using SixLabors.ImageSharp.Formats.Tiff; +using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using GL = OpenTK.Graphics.OpenGL4.GL; @@ -19,7 +25,6 @@ using TextureParameterName = OpenTK.Graphics.OpenGL4.TextureParameterName; using TextureTarget = OpenTK.Graphics.OpenGL4.TextureTarget; using TextureUnit = OpenTK.Graphics.OpenGL4.TextureUnit; using TextureWrapMode = OpenTK.Graphics.OpenGL4.TextureWrapMode; -using VertexAttribPointerType = OpenTK.Graphics.OpenGL4.VertexAttribPointerType; namespace GraphicsManager.Objects.Core; @@ -27,51 +32,125 @@ public class Texture { public static readonly Dictionary TextureShader = new (); - public int handel; - public int Location { get; set; } = 1; - - internal Texture(byte[] File, bool Rounded = false) + private static Configuration imgcfg = new( + new PngConfigurationModule(), + new JpegConfigurationModule(), + new GifConfigurationModule(), + new BmpConfigurationModule(), + new PbmConfigurationModule(), + new TgaConfigurationModule(), + new TiffConfigurationModule(), + new WebpConfigurationModule()) { - Image image = Image.Load(File); - if (Rounded) - { - image.Mutate(x => - { - x.Flip(FlipMode.Vertical); - if (image.Width <= image.Height) x.ConvertToAvatar(image.Width, image.Width/2); - else x.ConvertToAvatar(image.Height, image.Height/2); - }); - } - else - { - image.Mutate(x => - { - x.Flip(FlipMode.Vertical); - }); - } - + PreferContiguousImageBuffers = true + }; - Span pixels = new byte[4 * image.Width * image.Height].AsSpan(); - image.CopyPixelDataTo(pixels); + public int handel; + public Vector2i? RawSize = null; + public int Location { get; set; } = 1; + + private Texture(byte[] pixels, int Width, int Height) + { handel = GL.GenTexture(); + RawSize = new(Width, Height); GL.BindTexture(TextureTarget.Texture2D, handel); - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels.ToArray()); + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); } + + private Texture(Image image, Memory m) + { + handel = GL.GenTexture(); + GL.BindTexture(TextureTarget.Texture2D, handel); + RawSize = new(image.Width, image.Height); + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, ref m.Span[0]); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); + } + + + internal static Texture GetTexture(Stream File) + { + try + { + Image image = Image.Load(imgcfg, File); + image.Mutate(x => + { + x.Flip(FlipMode.Vertical); + }); + byte[] pixels = new byte[4 * image.Width * image.Height]; + image.CopyPixelDataTo(pixels); + Texture t = new(pixels, image.Width, image.Height); + pixels = Array.Empty(); + image.Dispose(); + return t; + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + } + + internal static Texture GetTexture(Stream File, TextureManager tm, bool Missing) + { + try + { + Image image = Image.Load(imgcfg, File); + image.Mutate(x => + { + x.Flip(FlipMode.Vertical); + }); + File.Position = 0; + Texture? t; + if (image.DangerousTryGetSinglePixelMemory(out Memory m)) + { + t = new(image, m); + image.Dispose(); + m = null; + } + else + { + _ = image.DangerousTryGetSinglePixelMemory(out Memory mm); + if (Missing) + { + File.Position = 0; + Console.WriteLine("Getting texture from stream failed, switching to Missing.png."); + image.Dispose(); + t = GetTexture(Tools.GetResourceStream("GraphicsManager.Resources.Textures.Missing.png"), tm, false); + } + else + { + File.Position = 0; + Console.WriteLine("Getting texture from stream failed, switching to fallback."); + t = GetTexture(File); + } + + } + return t; + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + } private Texture() { } - internal static Character GetChar(Font l, char charter) + internal static Character GetChar(Font l, char charter, uint PH) { try { - int last = 0; for (int i = 0; i < l.Fonts.Count; i++) @@ -80,17 +159,16 @@ public class Texture { try { - l.Fonts[i].SetPixelSizes(0, l.PixelHeight); + l.Fonts[i].SetPixelSizes(0, PH); l.Fonts[i].SelectCharmap(Encoding.Unicode); last = i; } - catch (Exception e) + catch { - Console.WriteLine($"no"); continue; } - ushort temp = ((ushort)charter); + ushort temp = (charter); if (l.Fonts[i].GetCharIndex(temp) == 0) continue; l.Fonts[i].LoadChar(temp, LoadFlags.Render, LoadTarget.Normal); GlyphSlot glyph = l.Fonts[i].Glyph; @@ -101,12 +179,12 @@ public class Texture Size = new Vector2(bitmap.Width, bitmap.Rows), Bearing = new Vector2(glyph.BitmapLeft, glyph.BitmapTop), Advance = glyph.Advance.X.Value, + AdvanceY = ((Math.Abs(l.Fonts[last].Descender) / (double)l.Fonts[last].UnitsPerEM) * 16) }; } catch (Exception ex) { Console.WriteLine(ex); - continue; } } List bad = new(); @@ -118,7 +196,7 @@ public class Texture try { tmp = new(Font.lib, Font._SystemPre[i], 0); - tmp.SetPixelSizes(0, l.PixelHeight); + tmp.SetPixelSizes(0, PH); tmp.SelectCharmap(Encoding.Unicode); } catch (Exception e) @@ -149,6 +227,7 @@ public class Texture Size = new Vector2(bitmap2.Width, bitmap2.Rows), Bearing = new Vector2(glyph2.BitmapLeft, glyph2.BitmapTop), Advance = glyph2.Advance.X.Value, + AdvanceY = ((Math.Abs(l.Fonts[last].Descender) / (double)l.Fonts[last].UnitsPerEM) * 16) }; } catch (Exception ex) @@ -168,7 +247,7 @@ public class Texture { Font._SystemPre.Remove(str); } - l.Fonts[last].SetPixelSizes(0, l.PixelHeight); + l.Fonts[last].SetPixelSizes(0, PH); l.Fonts[last].SelectCharmap(Encoding.Unicode); ushort temp22 = ((ushort)charter); @@ -181,17 +260,17 @@ public class Texture Size = new Vector2(bitmap22.Width, bitmap22.Rows), Bearing = new Vector2(glyph22.BitmapLeft, glyph22.BitmapTop), Advance = (int)glyph22.Advance.X.Value, + AdvanceY = ((Math.Abs(l.Fonts[last].Descender) / (double)l.Fonts[last].UnitsPerEM) * 16) }; } catch (Exception e) { - Console.WriteLine(1); Console.WriteLine(e); throw; } } - internal static Texture TextureForChar(IGLFWGraphicsContext con, Font l, char charter) + internal static Texture TextureForChar(IGLFWGraphicsContext con, FontInteraction l, char charter) { try { @@ -200,7 +279,7 @@ public class Texture Texture? t = null; int last = 0; - for (int i = 0; i < l.Fonts.Count; i++) + for (int i = 0; i < l.CurrentFont.Fonts.Count; i++) { try { @@ -208,7 +287,7 @@ public class Texture if (Label._characters[con][l].ContainsKey(charter)) return Label._characters[con][l][(ushort)charter].Texture; try { - l.Fonts[i].SetPixelSizes(0, l.PixelHeight); + l.CurrentFont.Fonts[i].SetPixelSizes(0, l.PixelHeight); last = i; } catch (Exception e) @@ -219,11 +298,11 @@ public class Texture - l.Fonts[i].SelectCharmap(Encoding.Unicode); + l.CurrentFont.Fonts[i].SelectCharmap(Encoding.Unicode); ushort temp = ((ushort)charter); - if (l.Fonts[i].GetCharIndex(temp) == 0) continue; - l.Fonts[i].LoadChar(temp, LoadFlags.Render, LoadTarget.Normal); - GlyphSlot glyph = l.Fonts[i].Glyph; + if (l.CurrentFont.Fonts[i].GetCharIndex(temp) == 0) continue; + l.CurrentFont.Fonts[i].LoadChar(temp, LoadFlags.Render, LoadTarget.Normal); + GlyphSlot glyph = l.CurrentFont.Fonts[i].Glyph; FTBitmap bitmap = glyph.Bitmap; t = new(); GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); @@ -244,6 +323,7 @@ public class Texture Bearing = new Vector2(glyph.BitmapLeft, glyph.BitmapTop), Advance = (int)glyph.Advance.X.Value, Texture = t, + AdvanceY = glyph.Advance.Y.Value }; Label._characters[con][l].Add(temp, cha); @@ -286,7 +366,7 @@ public class Texture tmp.LoadChar(temp2, LoadFlags.Render, LoadTarget.Normal); GlyphSlot glyph2 = tmp.Glyph; FTBitmap bitmap2 = glyph2.Bitmap; - l.AddSystemFontFace(Font._SystemPre[i]); + l.CurrentFont.AddSystemFontFace(Font._SystemPre[i]); t = new(); GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); @@ -306,6 +386,7 @@ public class Texture Bearing = new Vector2(glyph2.BitmapLeft, glyph2.BitmapTop), Advance = (int)glyph2.Advance.X.Value, Texture = t, + AdvanceY = glyph2.Advance.Y.Value }; Label._characters[con][l].Add(temp2, cha2); @@ -319,16 +400,16 @@ public class Texture } 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; - l.Fonts[last].SetPixelSizes(0, l.PixelHeight); + l.CurrentFont.Fonts[last].SetPixelSizes(0, l.PixelHeight); GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); GL.ActiveTexture(TextureUnit.Texture0); - l.Fonts[last].SelectCharmap(Encoding.Unicode); + l.CurrentFont.Fonts[last].SelectCharmap(Encoding.Unicode); ushort temp = ((ushort)charter); - l.Fonts[last].LoadChar(temp, LoadFlags.Render, LoadTarget.Normal); - GlyphSlot glyph = l.Fonts[0].Glyph; + l.CurrentFont.Fonts[last].LoadChar(temp, LoadFlags.Render, LoadTarget.Normal); + GlyphSlot glyph = l.CurrentFont.Fonts[0].Glyph; FTBitmap bitmap = glyph.Bitmap; if (t is null) t = new(); else return t; @@ -348,6 +429,7 @@ public class Texture Bearing = new Vector2(glyph.BitmapLeft, glyph.BitmapTop), Advance = (int)glyph.Advance.X.Value, Texture = t, + AdvanceY = glyph.Advance.Y.Value }; Label._characters[con][l].Add(temp, cha); @@ -357,15 +439,21 @@ public class Texture } catch (Exception e) { - Console.WriteLine(2); Console.WriteLine(e); throw; } } - public void Use(TextureUnit unit = TextureUnit.Texture0) + public Texture Clone() { - GL.ActiveTexture(unit); + return (Texture)MemberwiseClone(); + } + + public TextureUnit Unit = TextureUnit.Texture0; + + public void Use() + { + GL.ActiveTexture(Unit); GL.BindTexture(TextureTarget.Texture2D, handel); } } diff --git a/GraphicsManager/Objects/Core/TextureManager.cs b/GraphicsManager/Objects/Core/TextureManager.cs index 568ecd5..14f785a 100644 --- a/GraphicsManager/Objects/Core/TextureManager.cs +++ b/GraphicsManager/Objects/Core/TextureManager.cs @@ -9,7 +9,7 @@ public class TextureManager { public static readonly Dictionary TextureManagers = new(); - public readonly Dictionary TextureHashMap = new(); + private List _textures = new(); public static TextureManager GetTextureManager(IGLFWGraphicsContext context) { @@ -31,16 +31,21 @@ public class TextureManager Context = context; } - public IReadOnlyList Textures { get => TextureHashMap.Values.ToList().AsReadOnly(); } + public IReadOnlyList Textures { get => _textures.AsReadOnly(); } public void RemoveTexture(Texture Texture) { - foreach(KeyValuePair item in TextureHashMap.Where(kvp => kvp.Value == Texture).ToList()) - { - TextureHashMap.Remove(item.Key); - } + _textures.Remove(Texture); } + public Texture AddTexture(Stream TextureStream, bool UseMissing = true) + { + Context.MakeCurrent(); + Texture t = Texture.GetTexture(TextureStream, this, UseMissing); + _textures.Add(t); + return t; + } + /* public Texture AddTexture(byte[] Texture, bool Rounded = false) { List hash2 = SHA256.HashData(Texture).ToList(); @@ -50,5 +55,5 @@ public class TextureManager Context.MakeCurrent(); TextureHashMap.Add(hash, new(Texture, Rounded)); return TextureHashMap[hash]; - } + }*/ } \ No newline at end of file diff --git a/GraphicsManager/Objects/FlowLayout.cs b/GraphicsManager/Objects/FlowLayout.cs index 5ba5f66..e4b73fa 100644 --- a/GraphicsManager/Objects/FlowLayout.cs +++ b/GraphicsManager/Objects/FlowLayout.cs @@ -5,6 +5,7 @@ using GraphicsManager.Objects.Core; using OpenTK.Graphics.OpenGL; using OpenTK.Mathematics; using OpenTK.Windowing.Common; +using OpenTK.Windowing.Common.Input; using Timer = System.Timers.Timer; namespace GraphicsManager.Objects; @@ -125,7 +126,35 @@ public class FlowLayout : IRenderObject, IParent { if (Controls.Length > 0) arg.Location = new(0, Controls[Controls.Length - 1].Location.Y + Controls[Controls.Length - 1].Size.Y); else arg.Location = new(0, 0); + if (arg is IParent par2) + { + for (int i = 0; i < par2.Controls.Length; i++) + { + par2.Controls[i].Distance = new( + par2.Size.X - par2.Controls[i].Size.X - par2.Controls[i].Location.X, + par2.Size.Y - par2.Controls[i].Size.Y - par2.Controls[i].Location.Y); + + } + } arg.Size = new(Size.X, arg.Size.Y); + if (arg is IParent par) + { + for (int i = 0; i < par.Controls.Length; i++) + { + bool top = (par.Controls[i].Anchor & ObjectAnchor.Top) == ObjectAnchor.Top; + bool left = (par.Controls[i].Anchor & ObjectAnchor.Left) == ObjectAnchor.Left; + bool right = (par.Controls[i].Anchor & ObjectAnchor.Right) == ObjectAnchor.Right; + bool bottom = (par.Controls[i].Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom; + if (!top && !bottom) { par.Controls[i].Anchor |= ObjectAnchor.Top; top = true; } + if (!left && !right) { par.Controls[i].Anchor |= ObjectAnchor.Left; left = true; } + int lx = (left ? par.Controls[i].Location.X : Size.X - par.Controls[i].Distance.X - par.Controls[i].Size.X); + int ly = (top ? par.Controls[i].Location.Y : Size.Y - par.Controls[i].Distance.Y - par.Controls[i].Size.Y); + int sy = (bottom ? Size.Y - par.Controls[i].Distance.Y - ly : par.Controls[i].Size.Y); + int sx = (right ? Size.X - par.Controls[i].Distance.X - lx : par.Controls[i].Size.X); + par.Controls[i].Size = new(sx, sy); + par.Controls[i].Location = new(lx, ly); + } + } arg.Anchor = ObjectAnchor.Left | ObjectAnchor.Right | ObjectAnchor.Top; return Task.CompletedTask; } @@ -141,6 +170,12 @@ public class FlowLayout : IRenderObject, IParent if (MouseLeave is not null) _ = MouseLeave.Invoke(this); return Task.CompletedTask; } + + public MouseCursor HoverMouse + { + get => _bounds.HoverMouse; + set => _bounds.HoverMouse = value; + } private bool inside = false; private Task BoundsOnMouseEnter(IRenderObject arg) @@ -217,11 +252,11 @@ public class FlowLayout : IRenderObject, IParent BlockDraw = false; } } - public Vector2i ScissorLocation { get => _bounds.ScissorLocation; } + //public Vector2i ScissorLocation { get => _bounds.ScissorLocation; } public Vector2i Position => Location; public Vector2 LocationAsFloat { get => _bounds.LocationAsFloat; } - public Vector2i Distance { get => _bounds.Distance; internal set => _bounds.Distance = value; } + public Vector2i Distance { get => _bounds.Distance; set => _bounds.Distance = value; } public event Func? Clicked; public event Action MouseDown; public event Action KeyDown; @@ -251,6 +286,17 @@ public class FlowLayout : IRenderObject, IParent Window.MouseWheel += WindowOnMouseWheel; if (WindowLoaded is not null) WindowLoaded.Invoke(this); } + + public void ForceDistanceUpdate() + { + if (Parent is null) return; + ForceDistanceUpdate(Parent); + } + + public void ForceDistanceUpdate(IParent parent) + { + Distance = new(parent.Size.X - Size.X - Location.X, parent.Size.Y - Size.Y - Location.Y); + } public bool BlockDraw { get; set; } = false; Timer t; @@ -400,11 +446,48 @@ public class FlowLayout : IRenderObject, IParent } } + public bool dw; + public void Draw(int x, int y, int w, int h) { if (Loaded) { - _bounds.Draw(x,y,w,h); + int nx = x, ny = y, nw = w, nh = h; + + + if (Location.X > nw) + return; + else + { + nx += Location.X; + nw -= Location.X; + if (Size.X < nw) + nw = Size.X; + } + + if (Location.Y > nh) + return; + else + { + ny += Location.Y; + nh -= Location.Y; + if (Size.Y < nh) + nh = Size.Y; + } + if (dw) Console.WriteLine("Flowlayout\nLoc: {0}\nSize: {1}\n\nX: {2}\nY: {3}\nW: {4}\nH:{5}\n\nX: {6}\nY: {7}\nW: {8}\nH:{9}", + Location, + Size, + x, + y, + w, + h, + nx, + ny, + nw, + nh); + if (nw ==0 || nh == 0) return; + GL.Scissor(nx, Window!.Size.Y - ny - nh, nw, nh); + _bounds.Draw(nx,ny,nw,nh); IEnumerable needload = Controls.Where(a => a.Loaded == false); if (needload.Any()) @@ -419,25 +502,15 @@ public class FlowLayout : IRenderObject, IParent } for (int i = 0; i < Controls.Length; i++) { - Vector2i laff = new(Controls[i].ScissorLocation.X, Controls[i].ScissorLocation.Y); - Vector2i saff = new Vector2i(Controls[i].Size.X, Controls[i].Size.Y); - if (laff.X < ScissorLocation.X) laff = new(ScissorLocation.X, laff.Y); - if (laff.X < x) laff = new(x, laff.Y); - if (laff.Y < ScissorLocation.Y) laff = new(laff.X, ScissorLocation.Y); - if (laff.Y < y) laff = new(laff.X, y); - if (saff.X + laff.X > Size.X + ScissorLocation.X) saff = new(Size.X, saff.Y); - if (saff.Y + laff.Y > Size.Y + ScissorLocation.Y) saff = new(saff.X, Size.Y); - GL.Scissor(laff.X, laff.Y, saff.X, saff.Y); - Controls[i].Draw(ScissorLocation.X, ScissorLocation.Y, Size.X, Size.Y); + if (Controls[i] is not IParent) + { + GL.Scissor(nx, Window!.Size.Y - ny - nh, nw, nh); + } + Controls[i].Draw(nx, ny, nw, nh); } } } - - public Vector2i GetParentRelLocPoint() - { - return Parent!.GetParentRelLocPoint() + new Vector2i(Location.X, Parent.Size.Y - (Location.Y + Size.Y)); - } - + public void Clean() { for (int i = 0; i < Controls.Length; i++) diff --git a/GraphicsManager/Objects/Label.cs b/GraphicsManager/Objects/Label.cs index a001f78..fb5b35e 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.Common.Input; using OpenTK.Windowing.Desktop; using OpenTK.Windowing.GraphicsLibraryFramework; using SharpFont; @@ -12,10 +13,21 @@ using Encoding = SharpFont.Encoding; namespace GraphicsManager.Objects; -public class Label : IRenderObject +public class Label : ILabel { public static readonly Dictionary DefaultTextShader = new(); - public static readonly Font DefaultFont = Font.MakeFontFromSystem(); + //public static readonly Font DefaultFont = Core.Font.MakeFontFromSystem(); + + public Label(FontFamily fontFamily) + { + Font = FontInteraction.Load(fontFamily); + } + + public Label(FontInteraction interaction) + { + Font = interaction; + } + public ContextMenu? ContextMenu { get; set; } = null; public IParent? Parent { get; private set; } public ObjectAnchor Anchor { get; set; } = ObjectAnchor.Left | ObjectAnchor.Top; @@ -45,7 +57,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; } @@ -60,6 +72,9 @@ public class Label : IRenderObject public int VBO { get; private set; } public Vector2 DIR { get; set; } = new Vector2(1f, 0f); + public int TrueHeight = 0; + public int PostiveTrueHeight = 0; + public Vector2i GetSizeOfChar(int Index) { float addy = Font.PixelHeight * Scale, addx = 0F, char_x = 0F; @@ -76,9 +91,10 @@ public class Label : IRenderObject { char_x = 0f; addy += Font.PixelHeight * Scale; + addy += Font.ExtraLinePixels; continue; } - Character cha = Texture.GetChar(Font, character); + Character cha = Texture.GetChar(Font.CurrentFont, character, Font.PixelHeight); float w = cha.Size.X * Scale; float xrel = char_x + cha.Bearing.X * Scale; char_x += (cha.Advance >> 6) * Scale; @@ -94,7 +110,9 @@ public class Label : IRenderObject { if (value is null) value = string.Empty; text = value; - float addy = Font.PixelHeight * Scale, addx = 0F, char_x = 0F; + int line = 0; + double nl = 0; + double addy = 0f, addy2 =0f, addx = 0F, char_x = 0F; for (int i = 0; i < value.Length; i++) { char character; @@ -102,22 +120,30 @@ public class Label : IRenderObject character = value[i]; else character = PasswordChar.Value; - - + if (character == '\n') { char_x = 0f; - addy += Font.PixelHeight * Scale; + nl = addy; + line++; continue; } - Character cha = Texture.GetChar(Font, character); - float w = cha.Size.X * Scale; - float xrel = char_x + cha.Bearing.X * Scale; + Character cha = Texture.GetChar(Font.CurrentFont, character, Font.PixelHeight); + double w = cha.Size.X * Scale; + double xrel = char_x + cha.Bearing.X * Scale; + double yrel = ((cha.Size.Y - cha.Bearing.Y) * Scale) + (Font.PixelHeight * Scale); + yrel += nl; char_x += (cha.Advance >> 6) * Scale; if ((xrel + w) >= addx) addx = (xrel + w); + if (yrel > addy) addy = yrel; + if (line == 0) + { + if (addy2 < cha.Bearing.Y) addy2 = cha.Bearing.Y; + } } - - Size = new((int)addx, (int)addy); + Size = new((int)addx, (int)addy + (int)(line * Font.ExtraLinePixels)); + PostiveTrueHeight = (int)addy2; + TrueHeight = (int)(addy - (Font.PixelHeight - addy2)); if (Loaded) { @@ -141,11 +167,12 @@ public class Label : IRenderObject } } public Shader Shader { get; set; } = null!; - public Font Font { get; set; } = DefaultFont; + public FontInteraction Font { get; } public float Scale { get; set; } = 1.0f; public Color4 Color { get; set; } = new Color4(255, 255, 255, 255); - public Vector2i Distance { get; internal set; } + public Vector2i Distance { get; set; } private Vector2i loc_ = new(); + private int maxy = 0, maxx = 0; public Vector2i Location { get @@ -158,7 +185,7 @@ public class Label : IRenderObject if (Window is null || Parent is null) return; if (Window.CanControleUpdate && Loaded) { - ScissorLocation = Parent.GetParentRelLocPoint() + new Vector2i(Location.X, Parent.Size.Y - (loc_.Y + Size.Y)); + // = Parent.GetParentRelLocPoint() + new Vector2i(Location.X, Parent.Size.Y - (loc_.Y + Size.Y)); Parent!.TryDraw(); if (!Window.Context.IsCurrent) Window.Context.MakeCurrent(); } @@ -170,7 +197,7 @@ public class Label : IRenderObject set { _size = value; - if (Loaded && Parent is not null) ScissorLocation = Parent.GetParentRelLocPoint() + new Vector2i(Location.X, Parent.Size.Y - (loc_.Y + Size.Y)); + //if (Loaded && Parent is not null) ScissorLocation = Parent.GetParentRelLocPoint() + new Vector2i(Location.X, Parent.Size.Y - (loc_.Y + Size.Y)); } } @@ -199,7 +226,7 @@ public class Label : IRenderObject public void Draw(int x, int y, int ww, int hh) { - if (Visible & Loaded) + if (Visible && Loaded && this.Font is not null) { if (!Window!.Context.IsCurrent) Window.Context.MakeCurrent(); Shader.Use(); @@ -214,7 +241,7 @@ public class Label : IRenderObject float angle_rad = (float)Math.Atan2(DIR.Y, DIR.X); Matrix4 rotateM = Matrix4.CreateRotationZ(angle_rad); - Matrix4 transOriginM = Matrix4.CreateTranslation(new Vector3(loc_.X + Window.FloatToInt(Parent!.IntToFloat(0)), loc_.Y + Font.PixelHeight + Window.FloatToInt(Parent!.IntToFloat(0, true), true), 0f)); + Matrix4 transOriginM = Matrix4.CreateTranslation(new Vector3(loc_.X + Window.FloatToInt(Parent!.IntToFloat(0)), loc_.Y + (Font.PixelHeight * Scale) + Window.FloatToInt(Parent!.IntToFloat(0, true), true), 0f)); float char_x = 0.0f; GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); @@ -231,13 +258,14 @@ public class Label : IRenderObject bool n = (c == '\n'); if (!_characters[Window!.Context][Font].ContainsKey(c) && !n) { - var f = Texture.TextureForChar(Window!.Context, Font, c); + Texture f = Texture.TextureForChar(Window!.Context, Font, c); } int maxx = 0; if (n) { hhh += Font.PixelHeight * Scale; + hhh += Font.ExtraLinePixels; char_x = 0f; } else @@ -261,9 +289,14 @@ public class Label : IRenderObject GL.DrawArrays(PrimitiveType.Triangles, 0, 6); } } - - GL.Disable(EnableCap.Blend); - } + } + } + public void ForceDistanceUpdate() + { + } + + public void ForceDistanceUpdate(IParent parent) + { } public Window? Window { get; private set; } private static Dictionary> GlobalBuffers = new(); @@ -339,22 +372,39 @@ public class Label : IRenderObject if (!mouseinside && ContextMenu is not null) ContextMenu.HideContext(Window!); } + public MouseCursor HoverMouse { get; set; } = MouseCursor.Default; + private bool mouseinside = false; private void WindowOnMouseMove(MouseMoveEventArgs obj) { if (Visible && - Parent?.IntToFloat(Location.X) <= Window?.IntToFloat((float)Window?.MousePosition.X!) && + Parent?.IntToFloat(Location.X) <= Window?.IntToFloat((float)Window?.MousePosition.X!) && Parent?.IntToFloat(Size.X + Location.X) >= Window?.IntToFloat((float)Window?.MousePosition.X!) && Parent?.IntToFloat(Location.Y + Size.Y, true) <= Window?.IntToFloat((float)Window?.MousePosition.Y!, true) && Parent?.IntToFloat(Location.Y, true) >= Window?.IntToFloat((float)Window?.MousePosition.Y!, true)) { - if (MouseEnter is not null && !mouseinside) _ = MouseEnter.Invoke(this); - mouseinside = true; + if (!mouseinside) + { + if (Window!.CurrentTop is null || Window!.CurrentTop == this) + { + Window!.Cursor = HoverMouse; + if (MouseEnter is not null) _ = MouseEnter.Invoke(this); + mouseinside = true; + } + else + { + mouseinside = false; + } + } } else { - if (MouseLeave is not null && mouseinside) _ = MouseLeave.Invoke(this); - mouseinside = false; + if (mouseinside) + { + if (mouseinside && Window!.Cursor == HoverMouse) Window!.Cursor = Parent!.HoverMouse; + if (MouseLeave is not null && mouseinside) _ = MouseLeave.Invoke(this); + mouseinside = false; + } } } diff --git a/GraphicsManager/Objects/RainbowLabel.cs b/GraphicsManager/Objects/RainbowLabel.cs new file mode 100755 index 0000000..5dba769 --- /dev/null +++ b/GraphicsManager/Objects/RainbowLabel.cs @@ -0,0 +1,494 @@ +using GraphicsManager.Enums; +using GraphicsManager.Interfaces; +using GraphicsManager.Objects.Core; +using GraphicsManager.Structs; +using OpenTK.Graphics.OpenGL4; +using OpenTK.Mathematics; +using OpenTK.Windowing.Common; +using OpenTK.Windowing.Common.Input; +using OpenTK.Windowing.Desktop; +using OpenTK.Windowing.GraphicsLibraryFramework; +using SharpFont; +using Encoding = SharpFont.Encoding; + +namespace GraphicsManager.Objects; + +public class RainbowLabel : ILabel +{ + public RainbowLabel(FontFamily fontFamily) + { + Font = FontInteraction.Load(fontFamily); + } + + public RainbowLabel(FontInteraction interaction) + { + Font = interaction; + } + + 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(); + + public Vector2 LocationAsFloat { get { return laf; } } + public Vector2 SizeAsFloat { get { return saf; } } + private char? pc = null; + public char? PasswordChar + { + get => pc; + set + { + pc = value; + if (Parent is not null) Parent.TryDraw(); + } + } + private bool _Visible = true; + + public bool Visible + { + get => _Visible; + set + { + _Visible = value; + if (Parent is not null && Loaded) Parent.TryDraw(); + } + } + + private string text = string.Empty; + public int VAO { get; private set; } + + public void Focus() + { + + } + public void UnFocus() + { + + } + public int VBO { get; private set; } + public Vector2 DIR { get; set; } = new Vector2(1f, 0f); + + public int TrueHeight = 0; + public int PostiveTrueHeight = 0; + + public Vector2i GetSizeOfChar(int Index) + { + float addy = Font.PixelHeight * Scale, addx = 0F, char_x = 0F; + for (int i = 0; i < Index + 1; i++) + { + char character; + if (PasswordChar is null) + character = Text[i]; + else + character = PasswordChar.Value; + + + if (character == '\n') + { + char_x = 0f; + addy += Font.PixelHeight * Scale; + addy += Font.ExtraLinePixels; + continue; + } + Character cha = Texture.GetChar(Font.CurrentFont, character, Font.PixelHeight); + float w = cha.Size.X * Scale; + float xrel = char_x + cha.Bearing.X * Scale; + char_x += (cha.Advance >> 6) * Scale; + if ((xrel + w) >= addx) addx = (xrel + w); + } + + return new((int)addx, (int)addy); + } + public string Text + { + get => text; + set + { + if (value is null) value = string.Empty; + text = value; + int line = 0; + double nl = 0; + double addy = 0f, addy2 =0f, addx = 0F, char_x = 0F; + for (int i = 0; i < value.Length; i++) + { + char character; + if (PasswordChar is null) + character = value[i]; + else + character = PasswordChar.Value; + + if (character == '\n') + { + char_x = 0f; + nl = addy; + line++; + continue; + } + Character cha = Texture.GetChar(Font.CurrentFont, character, Font.PixelHeight); + double w = cha.Size.X * Scale; + double xrel = char_x + cha.Bearing.X * Scale; + double yrel = ((cha.Size.Y - cha.Bearing.Y) * Scale) + (Font.PixelHeight * Scale); + yrel += nl; + char_x += (cha.Advance >> 6) * Scale; + if ((xrel + w) >= addx) addx = (xrel + w); + if (yrel > addy) addy = yrel; + if (line == 0) + { + if (addy2 < cha.Bearing.Y) addy2 = cha.Bearing.Y; + } + } + Size = new((int)addx, (int)addy); + PostiveTrueHeight = (int)addy2; + TrueHeight = (int)(addy - (Font.PixelHeight - addy2)); + if (Loaded) + { + + if (Window is not null && Window.CanControleUpdate) + { + if (!Window.Context.IsCurrent) + { + try + { + Window.Context.MakeCurrent(); + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); + Parent!.TryDraw(); + } + } + } + } + public Shader Shader { get; set; } = null!; + public FontInteraction Font { get; } + public float Scale { get; set; } = 1.0f; + public Color4 Color { get; set; } = new Color4(255, 255, 255, 255); + public Vector2i Distance { get; set; } + private Vector2i loc_ = new(); + private int maxy = 0, maxx = 0; + public Vector2i Location + { + get + { + return loc_; + } + set + { + loc_ = value; + if (Window is null || Parent is null) return; + if (Window.CanControleUpdate && Loaded) + { + // = Parent.GetParentRelLocPoint() + new Vector2i(Location.X, Parent.Size.Y - (loc_.Y + Size.Y)); + Parent!.TryDraw(); + if (!Window.Context.IsCurrent) Window.Context.MakeCurrent(); + } + } + } + + private Vector2i _size; + public Vector2i Size { get => _size; + set + { + _size = value; + //if (Loaded && Parent is not null) ScissorLocation = Parent.GetParentRelLocPoint() + new Vector2i(Location.X, Parent.Size.Y - (loc_.Y + Size.Y)); + } + } + + public void Clean() + { + Tuple tup = GlobalBuffers[Window!.Context]; + if (tup.Item3 - 1 == 0) + { + //Broken, I may fix latter + + //if (!Window.Context.IsCurrent) Window.Context.MakeCurrent(); + //GL.DeleteBuffer(VBO); + //GL.DeleteVertexArray(VAO); + //GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + //GlobalBuffers.Remove(Window!.Context); + } + else + { + GlobalBuffers[Window!.Context] = new(tup.Item1, tup.Item2, tup.Item3 - 1); + } + Size = new(0, 0); + Loaded = false; + Visible = false; + } + public Vector2i ScissorLocation { get; private set; } + + public void Draw(int x, int y, int ww, int hh) + { + if (Visible && Loaded && this.Font is not null) + { + if (!Window!.Context.IsCurrent) Window.Context.MakeCurrent(); + Shader.Use(); + GL.Enable(EnableCap.Blend); + //GL.Uniform4(2, Color); + Matrix4 projectionM = Matrix4.CreateOrthographicOffCenter(0, Window!.Size.X, Window!.Size.Y, 0, -1.0f, 1.0f); + GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); + GL.UniformMatrix4(1, false, ref projectionM); + + GL.BindVertexArray(VAO); + + float angle_rad = (float)Math.Atan2(DIR.Y, DIR.X); + Matrix4 rotateM = Matrix4.CreateRotationZ(angle_rad); + Matrix4 transOriginM = Matrix4.CreateTranslation(new Vector3(loc_.X + Window.FloatToInt(Parent!.IntToFloat(0)), loc_.Y + (Font.PixelHeight * Scale) + Window.FloatToInt(Parent!.IntToFloat(0, true), true), 0f)); + float char_x = 0.0f; + + GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); + GL.ActiveTexture(TextureUnit.Texture0); + + float hhh = 0f; + for (int i = 0; i < Text.Length; i++) + { + var col = SetCol(i); + GL.Uniform4(2, col); + char c; + if (PasswordChar is null) + c = Text[i]; + else + c = PasswordChar.Value; + bool n = (c == '\n'); + if (!Label._characters[Window!.Context][Font].ContainsKey(c) && !n) + { + Texture f = Texture.TextureForChar(Window!.Context, Font, c); + } + + int maxx = 0; + if (n) + { + hhh += Font.PixelHeight * Scale; + hhh += Font.ExtraLinePixels; + char_x = 0f; + } + else + { + if (!Label._characters[Window!.Context][Font].ContainsKey(c)) continue; + Character ch = Label._characters[Window!.Context][Font][c]; + float w = ch.Size.X * Scale; + float h = ch.Size.Y * Scale; + float xrel = char_x + ch.Bearing.X * Scale; + float yrel = (ch.Size.Y - ch.Bearing.Y) * Scale; + yrel += hhh; + char_x += (ch.Advance >> 6) * Scale; + Matrix4 scaleM = Matrix4.CreateScale(new Vector3(w, h, 1.0f)); + Matrix4 transRelM = Matrix4.CreateTranslation(new Vector3(xrel, yrel, 0.0f)); + + Matrix4 modelM = scaleM * transRelM * rotateM * transOriginM; + GL.UniformMatrix4(0, false, ref modelM); + + ch.Texture.Use(); + + GL.DrawArrays(PrimitiveType.Triangles, 0, 6); + } + } + } + } + public void ForceDistanceUpdate() + { + } + + public void ForceDistanceUpdate(IParent parent) + { + } + public Color4 SetCol(int index) + { + double onefith = Math.Round((double)Text.Length / 5); + double twofith = Math.Round(onefith * 2); + double threefith = Math.Round(onefith * 3); + double fourfith = Math.Round(onefith * 4); + if (onefith < 1) + { + return Text.Length switch + { + 1 => new Color4(255,0,0,255), + 2 => index switch + { + 0 => new Color4(255, 0, 0, 255), + 1 => new Color4(255, 255, 0, 255) + }, + 3 => index switch + { + 0 => new Color4(255, 0, 0, 255), + 1 => new Color4(255, 255, 0, 255), + 2 => new Color4(0, 255, 0, 255) + }, + 4 => index switch + { + 0 => new Color4(255, 0, 0, 255), + 1 => new Color4(255, 255, 0, 255), + 2 => new Color4(0, 255, 0, 255), + 3 => new Color4(0, 255, 255, 255) + }, + 5 => index switch + { + 0 => new Color4(255, 0, 0, 255), + 1 => new Color4(255, 255, 0, 255), + 2 => new Color4(0, 255, 0, 255), + 3 => new Color4(0, 255, 255, 255), + 4 => new Color4(0, 0, 255, 255) + } + }; + } + else + { + double n = index + 1; + if (n <= onefith) + { + n = index / onefith; + if (n > 1) n = 1; + return new Color4(255, (byte)(n * 255),0,255); + } + else if (n <= twofith) + { + n = (index - onefith) / onefith; + if (n > 1) n = 1; + return new Color4((byte)(255 - (n * 255)), 255,0,255); + } + else if (n <= threefith) + { + n = (index - twofith) / onefith; + if (n > 1) n = 1; + return new Color4(0, 255,(byte)(n * 255),255); + } + else if (n <= fourfith) + { + n = (index - threefith) / onefith; + if (n > 1) n = 1; + return new Color4(0, (byte)(255 - (n * 255)),255,255); + } + else + { + n = (index - fourfith) / onefith; + if (n > 1) + { + n -= 1; + return new Color4(255, 0,(byte)(255 - (n * 255)),255); + } + else return new Color4((byte)(n * 255), 0,255,255); + } + } + } + public Window? Window { get; private set; } + private static Dictionary> GlobalBuffers = new(); + public void LoadToParent(IParent window, Window win) + { + if (Loaded) return; + if (!Label._characters.ContainsKey(win!.Context)) Label._characters.Add(win!.Context, new()); + if (!Label._characters[win!.Context].ContainsKey(Font)) Label._characters[win!.Context].Add(Font, new Dictionary()); + if (Shader is null) Shader = Label.DefaultTextShader[win.Context]; + Parent = window; + Window = win; + Window.MouseMove += WindowOnMouseMove; + Window.MouseDown += WindowOnMouseDown; + if (!Window!.Context.IsCurrent) Window.Context.MakeCurrent(); + GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); + GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4); + if (!GlobalBuffers.ContainsKey(win.Context)) + { + float[] vquad = + { + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 0.0f, 1.0f, 1.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f + }; + int _VBO = GL.GenBuffer(); + GL.BindBuffer(BufferTarget.ArrayBuffer, _VBO); + GL.BufferData(BufferTarget.ArrayBuffer, 4 * 6 * 4, vquad, BufferUsageHint.StaticDraw); + int _VAO = GL.GenVertexArray(); + GL.BindVertexArray(_VAO); + GL.EnableVertexAttribArray(0); + GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 4 * 4, 0); + GL.EnableVertexAttribArray(1); + GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 4 * 4, 2 * 4); + GlobalBuffers.Add(win.Context, new(_VBO, _VAO, 0)); + } + + Tuple tup = GlobalBuffers[win.Context]; + VBO = tup.Item1; + VAO = tup.Item2; + GlobalBuffers[win.Context] = new(VBO, VAO, tup.Item3 + 1); + + + +/* + VBO = GL.GenBuffer(); + GL.BindBuffer(BufferTarget.ArrayBuffer, VBO); + GL.BufferData(BufferTarget.ArrayBuffer, 4 * 6 * 4, vquad, BufferUsageHint.StaticDraw); + + VAO = GL.GenVertexArray(); + GL.BindVertexArray(VAO); + GL.EnableVertexAttribArray(0); + GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 4 * 4, 0); + GL.EnableVertexAttribArray(1); + GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 4 * 4, 2 * 4); +*/ + GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + GL.BindVertexArray(0); + + Loaded = true; + Text = Text; + 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); + } + + 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!); + } + + public MouseCursor HoverMouse { get; set; } = MouseCursor.Default; + + private bool mouseinside = false; + private void WindowOnMouseMove(MouseMoveEventArgs obj) + { + if (Visible && + Parent?.IntToFloat(Location.X) <= Window?.IntToFloat((float)Window?.MousePosition.X!) && + Parent?.IntToFloat(Size.X + Location.X) >= Window?.IntToFloat((float)Window?.MousePosition.X!) && + Parent?.IntToFloat(Location.Y + Size.Y, true) <= Window?.IntToFloat((float)Window?.MousePosition.Y!, true) && + Parent?.IntToFloat(Location.Y, true) >= Window?.IntToFloat((float)Window?.MousePosition.Y!, true)) + { + if (!mouseinside) + { + if (Window!.CurrentTop is null || Window!.CurrentTop == this) + { + Window!.Cursor = HoverMouse; + if (MouseEnter is not null) _ = MouseEnter.Invoke(this); + mouseinside = true; + } + else + { + mouseinside = false; + } + } + } + else + { + if (mouseinside) + { + if (mouseinside && Window!.Cursor == HoverMouse) Window!.Cursor = Parent!.HoverMouse; + if (MouseLeave is not null && mouseinside) _ = MouseLeave.Invoke(this); + mouseinside = false; + } + } + } + + 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 55556f7..9844c65 100755 --- a/GraphicsManager/Objects/Rectangle.cs +++ b/GraphicsManager/Objects/Rectangle.cs @@ -4,6 +4,7 @@ using GraphicsManager.Objects.Core; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; using OpenTK.Windowing.Common; +using OpenTK.Windowing.Common.Input; using OpenTK.Windowing.Desktop; using OpenTK.Windowing.GraphicsLibraryFramework; @@ -12,19 +13,21 @@ namespace GraphicsManager.Objects; public class Rectangle : ITextureObject { public static readonly Dictionary DefaultShader = new(); + public static readonly Dictionary DefaultAlphaShader = new(); + public static readonly Dictionary DefaultAlphaTextureShader = new(); public ObjectAnchor Anchor { get; set; } = ObjectAnchor.Left | ObjectAnchor.Top; - public Texture? Texture { get; set; } + public List Textures { get; set; } = new(); public ContextMenu? ContextMenu { get; set; } = null; public event Func? FilesDroped; public Rectangle(Texture? texture = null) { - Texture = texture; + if (texture is not null) Textures.Add(texture);; if (Points_ is null) { - bool tex = (Texture is null); + bool tex = (texture is null); Points_ = new float[(tex ? 12 : 20)]; if (!tex) { @@ -67,26 +70,41 @@ public class Rectangle : ITextureObject } } + public Action? OnDrawAction; + public Action? OnDrawExitAction; + public void Draw(int x, int y, int w, int h) { if (Visible && Loaded) { if (!Window!.Context.IsCurrent) Window.Context.MakeCurrent(); - if (Texture is not null) Texture.Use(); - Shader.Use(); - if (Texture is null) GL.Uniform4(0, BackgroundColor); - if (Texture is not null) + foreach (Texture tex in Textures) { - GL.Enable(EnableCap.Blend); - GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); - GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); + tex.Use(); + } + Shader.Use(); + if (!Textures.Any() || Shader.Handle == DefaultAlphaShader[Window!.Context].Handle) + { + GL.Uniform4(0, BackgroundColor); } GL.BindVertexArray(ArrayObject); GL.DrawElements(PrimitiveType.Triangles, Indexs.Length, DrawElementsType.UnsignedInt, 0); - if (Texture is not null) GL.Disable(EnableCap.Blend); } } + + public MouseCursor HoverMouse { get; set; } = MouseCursor.Default; + + public void ForceDistanceUpdate() + { + if (Parent is null) return; + ForceDistanceUpdate(Parent); + } + + public void ForceDistanceUpdate(IParent parent) + { + Distance = new(parent.Size.X - Size.X - Location.X, parent.Size.Y - Size.Y - Location.Y); + } public void Clean() { @@ -101,20 +119,24 @@ public class Rectangle : ITextureObject if (Loaded) return; this.Parent = Parent; this.Window = Window; - if (Shader is null) Shader = DefaultShader[Window.Context]; + if (Shader is null) + { + if (!Textures.Any())Shader = DefaultShader[Window.Context]; + else Shader = Texture.TextureShader[Window.Context]; + } int pos = Points.Length - 3; - if (Texture is not null) pos -= 2; + if (Textures.Any()) pos -= 2; pos = 4; - if (Texture is not null) pos += 2; + if (Textures.Any()) pos += 2; BufferObject = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ArrayBuffer, BufferObject); ArrayObject = GL.GenVertexArray(); GL.BindVertexArray(ArrayObject); int add = 3; - if (Texture is not null) add = 5; + if (Textures.Any()) add = 5; GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, add * sizeof(float), 0); - if (Texture is not null) + if (Textures.Any() && !Shader.ForTexture) { Shader = Texture.TextureShader[Window.Context]; } @@ -130,7 +152,7 @@ public class Rectangle : ITextureObject Window.MouseMove += WindowOnMouseMove; Window.FileDrop += WindowOnFileDrop; Location = Location; - Distance = new(Parent.Size.X - Size.X - Location.X, Parent.Size.Y - Size.Y - Location.Y); + if (Distance.X != 0 && Distance.Y != 0) Distance = new(Parent.Size.X - Size.X - Location.X, Parent.Size.Y - Size.Y - Location.Y); if (WindowLoaded is not null) WindowLoaded.Invoke(this); } @@ -149,13 +171,28 @@ public class Rectangle : ITextureObject Parent?.IntToFloat(Location.Y + Size.Y, true) <= Window?.IntToFloat((float)Window?.MousePosition.Y!, true) && Parent?.IntToFloat(Location.Y, true) >= Window?.IntToFloat((float)Window?.MousePosition.Y!, true)) { - if (MouseEnter is not null && !mouseinside) _ = MouseEnter.Invoke(this); - mouseinside = true; + if (!mouseinside) + { + if (Window!.CurrentTop is null || Window!.CurrentTop == this) + { + Window!.Cursor = HoverMouse; + if (MouseEnter is not null) _ = MouseEnter.Invoke(this); + mouseinside = true; + } + else + { + mouseinside = false; + } + } } else { - if (MouseLeave is not null && mouseinside) _ = MouseLeave.Invoke(this); - mouseinside = false; + if (mouseinside) + { + if (mouseinside && Window!.Cursor == HoverMouse) Window!.Cursor = Parent!.HoverMouse; + if (MouseLeave is not null && mouseinside) _ = MouseLeave.Invoke(this); + mouseinside = false; + } } } @@ -201,11 +238,12 @@ public class Rectangle : ITextureObject GL.BindBuffer(BufferTarget.ArrayBuffer, BufferObject); GL.BindVertexArray(ArrayObject); int add = 3; - if (Texture is not null) + if (Textures.Any()) { add = 5; - GL.VertexAttribPointer(Texture.Location, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); - GL.EnableVertexAttribArray(Texture.Location); + GL.EnableVertexAttribArray(Textures.First().Location); + GL.VertexAttribPointer(Textures.First().Location, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); + } GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, add * sizeof(float), 0); GL.EnableVertexAttribArray(0); @@ -230,12 +268,12 @@ public class Rectangle : ITextureObject public event Func? Clicked; - public bool Loaded { get; private set; } = false; + public bool Loaded { get; private set; } public event Func? WindowLoaded; public event Func? MouseEnter; public event Func? MouseLeave; - public object? Tag { get; set; } = null; - public Vector2i Distance { get; internal set; } + public object? Tag { get; set; } + public Vector2i Distance { get; set; } public Vector2i Size { @@ -251,10 +289,9 @@ public class Rectangle : ITextureObject float[] temp = Points; saf = new Vector2(Parent.IntToFloat(value.X + loc_.X, false), Parent.IntToFloat(value.Y + loc_.Y, true)); temp[0] = saf.X; - temp[(Texture is null ? 3 : 5)] = saf.X; - temp[(Texture is null ? 4 : 6)] = saf.Y; - temp[(Texture is null ? 7 : 11)] = saf.Y; - ScissorLocation = Parent.GetParentRelLocPoint() + new Vector2i(Location.X, Parent.Size.Y - (loc_.Y + value.Y)); + temp[(!Textures.Any()? 3 : 5)] = saf.X; + temp[(!Textures.Any() ? 4 : 6)] = saf.Y; + temp[(!Textures.Any() ? 7 : 11)] = saf.Y; Points = temp; } } @@ -271,23 +308,18 @@ public class Rectangle : ITextureObject if (Window is null || Parent is null) return; float[] temp = Points; laf = new Vector2(Parent.IntToFloat(value.X, false), Parent.IntToFloat(value.Y, true)); - temp[(Texture is null ? 6 : 10)] = laf.X; - temp[(Texture is null ? 9 : 15)] = laf.X; + temp[(!Textures.Any() ? 6 : 10)] = laf.X; + temp[(!Textures.Any() ? 9 : 15)] = laf.X; temp[1] = laf.Y; - temp[(Texture is null ? 10 : 16)] = laf.Y; + temp[(!Textures.Any() ? 10 : 16)] = laf.Y; saf = new Vector2(Parent.IntToFloat(Size.X + value.X, false), Parent.IntToFloat(Size.Y + value.Y, true)); temp[0] = saf.X; - temp[(Texture is null ? 3 : 5)] = saf.X; - temp[(Texture is null ? 4 : 6)] = saf.Y; - temp[(Texture is null ? 7 : 11)] = saf.Y; - ScissorLocation = Parent.GetParentRelLocPoint() + new Vector2i(value.X, Parent.Size.Y - (value.Y + Size.Y));// new((int)Window.FloatToInt(Parent.IntToFloat(value.X)), - //ScissorLocation = new Vector2i(ScissorLocation.X, Window.Size.Y - ScissorLocation.Y); - //(int)Window.FloatToInt(Parent.IntToFloat(value.Y, true), true) - //); + temp[(!Textures.Any() ? 3 : 5)] = saf.X; + temp[(!Textures.Any() ? 4 : 6)] = saf.Y; + temp[(!Textures.Any() ? 7 : 11)] = saf.Y; Points = temp; } } - public Vector2i ScissorLocation { get; private set; } private Vector2 laf = new(), saf = new(); public Vector2 LocationAsFloat { get { return laf; } } diff --git a/GraphicsManager/Objects/RoundedButton.cs b/GraphicsManager/Objects/RoundedButton.cs index 3929bd8..0143751 100755 --- a/GraphicsManager/Objects/RoundedButton.cs +++ b/GraphicsManager/Objects/RoundedButton.cs @@ -2,8 +2,7 @@ using GraphicsManager.Interfaces; using GraphicsManager.Objects.Core; using OpenTK.Mathematics; -using OpenTK.Windowing.Common; -using OpenTK.Windowing.GraphicsLibraryFramework; +using OpenTK.Windowing.Common.Input; namespace GraphicsManager.Objects; @@ -11,11 +10,27 @@ public class RoundedButton : IRenderObject { private RoundedRectangle _bounds, _inside; internal Label _label; - public RoundedButton() + public RoundedButton(FontFamily family) { _bounds = new RoundedRectangle(); _inside = new RoundedRectangle(); - _label = new Label(); + _label = new Label(family); + _bounds.MouseEnter += BoundsOnMouseEnter; + _bounds.MouseLeave += BoundsOnMouseLeave; + _bounds.Clicked += BoundsOnClicked; + } + + public MouseCursor HoverMouse + { + get => _bounds.HoverMouse; + set => _bounds.HoverMouse = value; + } + + public RoundedButton(FontInteraction family) + { + _bounds = new RoundedRectangle(); + _inside = new RoundedRectangle(); + _label = new Label(family); _bounds.MouseEnter += BoundsOnMouseEnter; _bounds.MouseLeave += BoundsOnMouseLeave; _bounds.Clicked += BoundsOnClicked; @@ -47,7 +62,7 @@ public class RoundedButton : IRenderObject 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 FontInteraction Font { get => _label.Font; } 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; } @@ -64,6 +79,18 @@ public class RoundedButton : IRenderObject _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 void ForceDistanceUpdate() + { + if (Parent is null) return; + ForceDistanceUpdate(Parent); + } + + public void ForceDistanceUpdate(IParent parent) + { + _bounds.ForceDistanceUpdate(parent); + } + public Vector2i Location { get => _bounds.Location; set @@ -73,11 +100,11 @@ public class RoundedButton : IRenderObject _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 Vector2i ScissorLocation { get => _bounds.ScissorLocation; } + //public Vector2i ScissorLocation { get => _bounds.ScissorLocation; } public Vector2 SizeAsFloat { get => _bounds.SizeAsFloat; } public Vector2 LocationAsFloat { get => _bounds.LocationAsFloat; } - public Vector2i Distance { get => _bounds.Distance; internal set => _bounds.Distance = value;} + public Vector2i Distance { get => _bounds.Distance; set => _bounds.Distance = value;} public IParent? Parent { get; private set; } = null; public Window? Window { get; private set; } = null; public Color4 InsideColor { get => _inside.BackgroundColor; set => _inside.BackgroundColor = value; } diff --git a/GraphicsManager/Objects/RoundedRectangle.cs b/GraphicsManager/Objects/RoundedRectangle.cs index 0597a9d..16e18fb 100755 --- a/GraphicsManager/Objects/RoundedRectangle.cs +++ b/GraphicsManager/Objects/RoundedRectangle.cs @@ -5,6 +5,7 @@ using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; using OpenTK.Windowing.GraphicsLibraryFramework; using OpenTK.Windowing.Common; +using OpenTK.Windowing.Common.Input; namespace GraphicsManager.Objects; @@ -114,10 +115,8 @@ public class RoundedRectangle : IRenderObject if (Visible && Loaded) { GL.Enable(EnableCap.Multisample); - GL.Hint(HintTarget.PointSmoothHint, HintMode.Nicest); GL.Hint(HintTarget.LineSmoothHint, HintMode.Nicest); GL.Hint(HintTarget.PolygonSmoothHint, HintMode.Nicest); - GL.Hint(HintTarget.PointSmoothHint, HintMode.Nicest); Shader.Use(); GL.Uniform4(0, BackgroundColor); GL.BindVertexArray(ArrayObject); @@ -168,13 +167,28 @@ public class RoundedRectangle : IRenderObject Parent?.IntToFloat(Location.Y + Size.Y, true) <= Window?.IntToFloat((float)Window?.MousePosition.Y!, true) && Parent?.IntToFloat(Location.Y, true) >= Window?.IntToFloat((float)Window?.MousePosition.Y!, true)) { - if (MouseEnter is not null && !mouseinside) _ = MouseEnter.Invoke(this); - mouseinside = true; + if (!mouseinside) + { + if (Window!.CurrentTop is null || Window!.CurrentTop == this) + { + Window!.Cursor = HoverMouse; + if (MouseEnter is not null) _ = MouseEnter.Invoke(this); + mouseinside = true; + } + else + { + mouseinside = false; + } + } } else { - if (MouseLeave is not null && mouseinside) _ = MouseLeave.Invoke(this); - mouseinside = false; + if (mouseinside) + { + if (mouseinside && Window!.Cursor == HoverMouse) Window!.Cursor = Parent!.HoverMouse; + if (MouseLeave is not null && mouseinside) _ = MouseLeave.Invoke(this); + mouseinside = false; + } } } @@ -248,12 +262,25 @@ public class RoundedRectangle : IRenderObject 3, 22, 23, 3, 4, 23}; public BufferUsageHint Hint { get; set; } = BufferUsageHint.StaticDraw; + + public MouseCursor HoverMouse { get; set; } = MouseCursor.Default; + + public void ForceDistanceUpdate() + { + if (Parent is null) return; + ForceDistanceUpdate(Parent); + } + + public void ForceDistanceUpdate(IParent parent) + { + Distance = new(parent.Size.X - Size.X - Location.X, parent.Size.Y - Size.Y - Location.Y); + } public event Func? Clicked; public bool Loaded { get; private set; } = false; - public Vector2i Distance { get; internal set; } + public Vector2i Distance { get; set; } public Vector2i Size { @@ -268,7 +295,7 @@ public class RoundedRectangle : IRenderObject Parent.ReportSizeUpdate(this); Location = Location; saf = new Vector2(Parent.IntToFloat(value.X + loc_.X, false), Parent.IntToFloat(value.Y + loc_.Y, true)); - ScissorLocation = Parent.GetParentRelLocPoint() + new Vector2i(Location.X, Parent.Size.Y - (loc_.Y + value.Y)); + //ScissorLocation = Parent.GetParentRelLocPoint() + new Vector2i(Location.X, Parent.Size.Y - (loc_.Y + value.Y)); } } @@ -333,11 +360,11 @@ public class RoundedRectangle : IRenderObject //ScissorLocation = Parent.GetParentRelLocPoint() + value; //ScissorLocation = Parent.GetParentRelLocPoint() + value;// new((int)Window.FloatToInt(Parent.IntToFloat(value.X)), //ScissorLocation = new Vector2i(ScissorLocation.X, Window.Size.Y - ScissorLocation.Y); - ScissorLocation = Parent.GetParentRelLocPoint() + new Vector2i(value.X, Parent.Size.Y - (value.Y + Size.Y)); + //ScissorLocation = Parent.GetParentRelLocPoint() + new Vector2i(value.X, Parent.Size.Y - (value.Y + Size.Y)); Points = temp.ToArray(); } } - public Vector2i ScissorLocation { get; private set; } + //public Vector2i ScissorLocation { get; private set; } private Vector2 laf = new(), saf = new(); public Vector2 LocationAsFloat { get { return laf; } } diff --git a/GraphicsManager/Objects/TabControl.cs b/GraphicsManager/Objects/TabControl.cs index bf4e469..8cd4d9e 100644 --- a/GraphicsManager/Objects/TabControl.cs +++ b/GraphicsManager/Objects/TabControl.cs @@ -4,6 +4,7 @@ using GraphicsManager.Objects.Core; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; using OpenTK.Windowing.Common; +using OpenTK.Windowing.Common.Input; using SixLabors.ImageSharp.Processing; namespace GraphicsManager.Objects; @@ -12,13 +13,27 @@ public class TabControl : IRenderObject, IParent { public Rectangle _bounds; - public TabControl() + public TabControl(FontFamily fam) { + TitleFont = FontInteraction.Load(fam); _bounds = new(); } + + public TabControl(FontInteraction fam) + { + TitleFont = fam; + _bounds = new(); + } + + public MouseCursor HoverMouse + { + get => _bounds.HoverMouse; + set => _bounds.HoverMouse = value; + } + private ControlList Buttonts = new(); - private ControlList Controls = new(); + public ControlList Controls { get; } = new(); public void AddPage(string Title, UserControl page) { @@ -30,10 +45,9 @@ public class TabControl : IRenderObject, IParent locc = Buttonts[loc - 1].Location.X; loccc = Buttonts[loc - 1].Size.X; } - Buttonts.Add(tmp = new RoundedButton() + Buttonts.Add(tmp = new RoundedButton(TitleFont.Family) { Location = new( locc+ loccc + (TabSpace * (int)loc) + Border, Border), - Font = TitleFont, Text = Title, Tag = loc, BorderColor = this.BorderColor, @@ -61,10 +75,9 @@ public class TabControl : IRenderObject, IParent locc = Buttonts[loc - 1].Location.X; loccc = Buttonts[loc - 1].Size.X; } - Buttonts.Add(tmp = new RoundedButton() + Buttonts.Add(tmp = new RoundedButton(TitleFont) { Location = new( locc+ loccc + (TabSpace * (int)loc) + Border, Border), - Font = TitleFont, Text = Title, Tag = loc, BorderColor = this.BorderColor, @@ -88,6 +101,17 @@ public class TabControl : IRenderObject, IParent PageIndex = (uint)arg.Tag!; return Task.CompletedTask; } + + public void ForceDistanceUpdate() + { + if (Parent is null) return; + ForceDistanceUpdate(Parent); + } + + public void ForceDistanceUpdate(IParent parent) + { + _bounds.ForceDistanceUpdate(parent); + } public Color4 TextColor { get; set; } = new(255, 255, 255, 255); public Color4 BorderColor { get; set; } = new(40, 40, 40, 255); @@ -98,7 +122,7 @@ public class TabControl : IRenderObject, IParent public int TabSpace { get; set; } = 5; public int Border { get; set; } = 10; public IParent? Parent { get; private set; } = null; - public Font TitleFont { get; set; } = Label.DefaultFont; + public FontInteraction TitleFont { get; set; } = null!; public Window? Window { get; private set; } = null; public bool Visible @@ -125,9 +149,9 @@ public class TabControl : IRenderObject, IParent public Vector2i Size { get => _bounds.Size; set => _bounds.Size = value; } public Vector2i Location { get => _bounds.Location; set => _bounds.Location = value; } public ContextMenu? ContextMenu { get => _bounds.ContextMenu; set => _bounds.ContextMenu = value; } - public Vector2i Distance { get => _bounds.Distance; internal set => _bounds.Distance = value; } + public Vector2i Distance { get => _bounds.Distance; set => _bounds.Distance = value; } public Vector2 LocationAsFloat { get => _bounds.LocationAsFloat; } - public Vector2i ScissorLocation { get => _bounds.ScissorLocation; } + //public Vector2i ScissorLocation { get => _bounds.ScissorLocation; } public Vector2 SizeAsFloat { get => _bounds.SizeAsFloat; } private uint pgi = 0; public uint PageIndex @@ -251,19 +275,14 @@ public class TabControl : IRenderObject, IParent _bounds.Draw(x,y,w,h); if (!(Controls.Length >= (PageIndex))) return; if (!Controls[PageIndex].Loaded) return; - GL.Scissor(Controls[PageIndex].ScissorLocation.X, Controls[PageIndex].ScissorLocation.Y, Controls[PageIndex].Size.X, Controls[PageIndex].Size.Y); + // GL.Scissor(Controls[PageIndex].ScissorLocation.X, Controls[PageIndex].ScissorLocation.Y, Controls[PageIndex].Size.X, Controls[PageIndex].Size.Y); Controls[PageIndex].Draw(x,y,w,h); - GL.Scissor(ScissorLocation.X, ScissorLocation.Y, Size.X, Size.Y); + //GL.Scissor(ScissorLocation.X, ScissorLocation.Y, Size.X, Size.Y); for (int i = 0; i < Buttonts.Length; i++) Buttonts[i].Draw(x,y,w,h); } } - public Vector2i GetParentRelLocPoint() - { - return Parent!.GetParentRelLocPoint() + new Vector2i(Location.X, Parent.Size.Y - (Location.Y + Size.Y)); - } - public void Clean() { for (int i = 0; i < Controls.Length; i++) diff --git a/GraphicsManager/Objects/Textbox.cs b/GraphicsManager/Objects/Textbox.cs index c144216..5b53ca6 100755 --- a/GraphicsManager/Objects/Textbox.cs +++ b/GraphicsManager/Objects/Textbox.cs @@ -1,12 +1,10 @@ -using System.Timers; -using System.Timers; -using GraphicsManager.Enums; +using GraphicsManager.Enums; using GraphicsManager.Interfaces; using GraphicsManager.Objects.Core; -using OpenTK.Graphics.GL; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; using OpenTK.Windowing.Common; +using OpenTK.Windowing.Common.Input; using OpenTK.Windowing.GraphicsLibraryFramework; namespace GraphicsManager.Objects; @@ -17,12 +15,34 @@ public class Textbox : IRenderObject private Label _label; private Label _watermark; public ContextMenu? ContextMenu { get => _bounds.ContextMenu; set => _bounds.ContextMenu = value; } - public Textbox() + + public TextLocation TextLocation { get; set; } = TextLocation.TopLeft; + public Textbox(FontFamily LabelFam, FontFamily WaterFam) { _bounds = new RoundedRectangle(); _inside = new RoundedRectangle(); - _label = new Label(); - _watermark = new() + _label = new Label(LabelFam); + _watermark = new(WaterFam) + { + Color = new(128, 128, 128, 255) + }; + + _bounds.MouseEnter += BoundsOnMouseEnter; + _bounds.MouseLeave += BoundsOnMouseLeave; + } + + public MouseCursor HoverMouse + { + get => _bounds.HoverMouse; + set => _bounds.HoverMouse = value; + } + + public Textbox(FontInteraction LabelFam, FontInteraction WaterFam) + { + _bounds = new RoundedRectangle(); + _inside = new RoundedRectangle(); + _label = new Label(LabelFam); + _watermark = new(WaterFam) { Color = new(128, 128, 128, 255) }; @@ -41,27 +61,68 @@ public class Textbox : IRenderObject 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 FontInteraction Font { get => _label.Font; } public string Text { get => _label.Text; set { + int oldh = _label.TrueHeight; + _label.Text = value; if (!string.IsNullOrEmpty(value)) { - if (!_label.Visible) _label.Visible = true; + bool f = false; + if (!_label.Visible) + { + f = true; + _label.Visible = true; + _label.Location = TextLocation switch + { + TextLocation.TrueCenterLeft => new(Location.X + Border + 5, Location.Y + ((Size.Y - _label.TrueHeight) / 2) - (_label.Size.Y - _label.TrueHeight)), + TextLocation.PostiveTureCenterLeft => new(Location.X + Border + 5, Location.Y + ((Size.Y - _label.PostiveTrueHeight) / 2) - _label.Size.Y + _label.TrueHeight), + TextLocation.PxLeft => new(Location.X + Border + 5, Location.Y + ((Size.Y - _label.Size.Y) / 2)), + TextLocation.TopLeft or _ => new(Location.X + Border + 5, Location.Y + Border + 5) + }; + _watermark.Location = _label.Location; + } if (_watermark.Visible) _watermark.Visible = false; + if (!f && TextLocation == TextLocation.TrueCenterLeft && oldh != _label.TrueHeight) + { + _label.Location = new(Location.X + Border + 5, Location.Y + ((Size.Y - _label.TrueHeight) / 2) - (_label.Size.Y - _label.TrueHeight)); + _watermark.Location = _label.Location; + } } else { if (_label.Visible) _label.Visible = false; - if (!_watermark.Visible) _watermark.Visible = true; + if (!_watermark.Visible) + { + _watermark.Visible = true; + _watermark.Location = TextLocation switch + { + TextLocation.TrueCenterLeft => new(Location.X + Border + 5, Location.Y + ((Size.Y - _watermark.TrueHeight) / 2) - (_watermark.Size.Y - _watermark.TrueHeight)), + TextLocation.PostiveTureCenterLeft => new(Location.X + Border + 5, Location.Y + ((Size.Y - _label.PostiveTrueHeight) / 2) - _label.Size.Y + _label.TrueHeight), + TextLocation.PxLeft => new(Location.X + Border + 5, Location.Y + ((Size.Y - _watermark.Size.Y) / 2)), + TextLocation.TopLeft or _ => new(Location.X + Border + 5, Location.Y + Border + 5) + }; + _label.Location = _label.Location; + } } - _label.Text = value; } } + + public void ForceDistanceUpdate() + { + if (Parent is null) return; + ForceDistanceUpdate(Parent); + } + + public void ForceDistanceUpdate(IParent parent) + { + _bounds.ForceDistanceUpdate(parent); + } - public Font WatermarkFont { get => _watermark!.Font; set => _watermark.Font = value; } + public FontInteraction WatermarkFont { get => _watermark!.Font!; } public string WatermarkText { get @@ -92,14 +153,34 @@ public class Textbox : IRenderObject set { _bounds.Location = value; - _label.Location = new(value.X + Border + 5, Location.Y + Border + Border + (((Size.Y - (Radius * 2)) / 2) - (_label.Size.Y / 2))); - _watermark.Location = _label.Location; + if (_watermark.Visible && !string.IsNullOrEmpty(_watermark.Text)) + { + _watermark.Location = TextLocation switch + { + TextLocation.TrueCenterLeft => new(value.X + Border + 5, value.Y + ((Size.Y - _watermark.TrueHeight) / 2) - (_watermark.Size.Y - _watermark.TrueHeight)), + TextLocation.PostiveTureCenterLeft => new(value.X + Border + 5, value.Y + ((Size.Y - _label.PostiveTrueHeight) / 2) - _label.Size.Y + _label.TrueHeight), + TextLocation.PxLeft => new(value.X + Border + 5, value.Y + ((Size.Y - _watermark.Size.Y) / 2)), + TextLocation.TopLeft or _ => new(value.X + Border + 5, value.Y + Border + 5) + }; + _label.Location = _watermark.Location; + } + else + { + _label.Location = TextLocation switch + { + TextLocation.TrueCenterLeft => new(value.X + Border + 5, value.Y + ((Size.Y - _label.TrueHeight) / 2) - (_label.Size.Y - _label.TrueHeight)), + TextLocation.PostiveTureCenterLeft => new(value.X + Border + 5, value.Y + ((Size.Y - _label.PostiveTrueHeight) / 2) - _label.Size.Y + _label.TrueHeight), + TextLocation.PxLeft => new(value.X + Border + 5, value.Y + ((Size.Y - _label.Size.Y) / 2)), + TextLocation.TopLeft or _ => new(value.X + Border + 5, value.Y + Border + 5) + }; + _watermark.Location = _label.Location; + } _inside.Location = new(value.X + Border, value.Y + Border); } } public Vector2 SizeAsFloat { get => _bounds.SizeAsFloat; } public Vector2 LocationAsFloat { get => _bounds.LocationAsFloat; } - public Vector2i Distance { get => _bounds.Distance; internal set => _bounds.Distance = value; } + public Vector2i Distance { get => _bounds.Distance; set => _bounds.Distance = value; } public IParent? Parent { get; private set; } = null; public Window? Window { get; private set; } = null; public Color4 InsideColor { get => _inside.BackgroundColor; set => _inside.BackgroundColor = value; } @@ -156,7 +237,7 @@ public class Textbox : IRenderObject } private Vector2i? l = null, s = null; - public Vector2i ScissorLocation { get => _bounds.ScissorLocation; } + //public Vector2i ScissorLocation { get => _bounds.ScissorLocation; } public void Draw(int x, int y, int w, int h) { @@ -169,18 +250,9 @@ public class Textbox : IRenderObject (int)Window.FloatToInt(Parent.IntToFloat(_inside.Location.Y, true), true)); s = new(_inside.Size.X - _label.Location.X + Location.X, _inside.Size.Y); - Console.WriteLine(_inside.Location.Y); - Console.WriteLine($"x:{l.Value.X} y:{l.Value.Y} xx:{s.Value.X} yy:{s.Value.Y}"); l = new(l.Value.X, 0); s = new(s.Value.X, Window.Size.Y); } - GL.Disable(EnableCap.ScissorTest); - GL.Enable(EnableCap.ScissorTest); - GL.Scissor(l.Value.X, - l.Value.Y, - s.Value.X, - s.Value.Y - ); if (!string.IsNullOrEmpty(_label.Text)) _label.Draw(x,y,w,h); else _watermark.Draw(x,y,w,h); } diff --git a/GraphicsManager/Objects/TexturedTextBox.cs b/GraphicsManager/Objects/TexturedTextBox.cs new file mode 100755 index 0000000..ec8679d --- /dev/null +++ b/GraphicsManager/Objects/TexturedTextBox.cs @@ -0,0 +1,393 @@ +using GraphicsManager.Enums; +using GraphicsManager.Interfaces; +using GraphicsManager.Objects.Core; +using OpenTK.Graphics.OpenGL4; +using OpenTK.Mathematics; +using OpenTK.Windowing.Common; +using OpenTK.Windowing.Common.Input; +using OpenTK.Windowing.GraphicsLibraryFramework; + +namespace GraphicsManager.Objects; + +public class TexturedTextBox : IRenderObject +{ + private Rectangle[] _bounds; + private Label _label; + private Label _watermark; + public ContextMenu? ContextMenu { get; set; } + + public TextLocation TextLocation { get; set; } = TextLocation.TopLeft; + + public TexturedTextBox(Texture Left, Texture Middle, Texture Right, FontFamily LabelFam, FontFamily WaterFam) + { + _label = new Label(LabelFam); + _watermark = new(WaterFam) + { + Color = new(128, 128, 128, 255) + }; + _bounds = new Rectangle[] {new(Left), new(Middle), new(Right) }; + } + + public MouseCursor HoverMouse + { + get => _bounds[0].HoverMouse; + set + { + for (int i = 0; i < _bounds.Length; i++) + { + _bounds[i].HoverMouse = value; + } + + _watermark.HoverMouse = value; + _label.HoverMouse = value; + } + } + + public int Border { get; set; } = 2; + + public TexturedTextBox(Texture Left, Texture Middle, Texture Right, FontInteraction LabelFam, FontInteraction WaterFam) + { + _label = new Label(LabelFam); + _watermark = new(WaterFam) + { + Color = new(128, 128, 128, 255) + }; + _bounds = new Rectangle[] {new(Left), new(Middle), new(Right) }; + } + + private bool mouseinside; + + private void WindowOnMouseMove(MouseMoveEventArgs e) + { + if (Visible && + Parent?.IntToFloat(Location.X) <= Window?.IntToFloat((float)Window?.MousePosition.X!) && + Parent?.IntToFloat(Size.X + Location.X) >= Window?.IntToFloat((float)Window?.MousePosition.X!) && + Parent?.IntToFloat(Location.Y + Size.Y, true) <= Window?.IntToFloat((float)Window?.MousePosition.Y!, true) && + Parent?.IntToFloat(Location.Y, true) >= Window?.IntToFloat((float)Window?.MousePosition.Y!, true)) + { + if (!mouseinside) + { + if (Window!.CurrentTop is null || Window!.CurrentTop == this) + { + Window!.Cursor = HoverMouse; + if (MouseEnter is not null) _ = MouseEnter.Invoke(this); + mouseinside = true; + } + else + { + mouseinside = false; + } + } + } + else + { + if (mouseinside) + { + if (mouseinside && Window!.Cursor == HoverMouse) Window!.Cursor = Parent!.HoverMouse; + if (MouseLeave is not null && mouseinside) _ = MouseLeave.Invoke(this); + mouseinside = false; + } + } + } + + //private int CurrentIndex = 0; + + public event Func? WindowLoaded; + public event Func? MouseEnter; + public event Func? MouseLeave; + public object? Tag { get; set; } = null; + public ObjectAnchor Anchor { get; set; } + public FontInteraction Font { get => _label.Font; } + public string Text + { + get => _label.Text; + set + { + int old = _label.TrueHeight; + _label.Text = value; + if (!string.IsNullOrEmpty(value)) + { + bool f = false; + if (!_label.Visible) + { + f = true; + _label.Visible = true; + _label.Location = TextLocation switch + { + TextLocation.TrueCenterLeft => new(Location.X + Border + 5, Location.Y + ((Size.Y - _label.TrueHeight) / 2) - (_label.Size.Y - _label.TrueHeight)), + TextLocation.PostiveTureCenterLeft => new(Location.X + Border + 5, Location.Y + ((Size.Y - _label.PostiveTrueHeight) / 2) - _label.Size.Y + _label.TrueHeight), + TextLocation.PxLeft => new(Location.X + Border + 5, Location.Y + ((Size.Y - _label.Size.Y) / 2)), + _ => new(Location.X + Border + 5, Location.Y + Border + 5) + }; + _watermark.Location = _label.Location; + } + if (_watermark.Visible) _watermark.Visible = false; + if (!f && TextLocation == TextLocation.TrueCenterLeft && old != _label.TrueHeight) + { + _label.Location = new(Location.X + Border + 5, Location.Y + ((Size.Y - _label.TrueHeight) / 2) - (_label.Size.Y - _label.TrueHeight)); + _watermark.Location = _label.Location; + } + } + else + { + if (_label.Visible) _label.Visible = false; + if (!_watermark.Visible) + { + _watermark.Visible = true; + _watermark.Location = TextLocation switch + { + TextLocation.TrueCenterLeft => new(Location.X + Border + 5, Location.Y + ((Size.Y - _watermark.TrueHeight) / 2) - (_watermark.Size.Y - _watermark.TrueHeight)), + TextLocation.PostiveTureCenterLeft => new(Location.X + Border + 5, Location.Y + ((Size.Y - _label.PostiveTrueHeight) / 2) - _label.Size.Y + _label.TrueHeight), + TextLocation.PxLeft => new(Location.X + Border + 5, Location.Y + ((Size.Y - _watermark.Size.Y) / 2)), + _ => new(Location.X + Border + 5, Location.Y + Border + 5) + }; + _label.Location = _label.Location; + } + } + } + } + + public void ForceDistanceUpdate() + { + if (Parent is null) return; + ForceDistanceUpdate(Parent); + } + + public void ForceDistanceUpdate(IParent parent) + { + Distance = new(parent.Size.X - Size.X - Location.X, parent.Size.Y - Size.Y - Location.Y); + } + + public FontInteraction WatermarkFont { get => _watermark.Font; } + public string WatermarkText + { + get + { + return _watermark.Text; + } + set + { + _watermark.Text = value; + } + } + public char? PasswordChar { get => _label.PasswordChar; set => _label.PasswordChar = value; } + public bool Loaded { get; private set; } + private Vector2i _size; + public Vector2i Size + { + get + { + return _size; + } + set + { + if (_size == value) return; + _bounds[0].Size = new(value.Y); + _bounds[1].Size = new(value.X - (_bounds[0].Size.X * 2), value.Y); + _bounds[2].Size = _bounds[0].Size; + if (_size.X != value.X) + { + _bounds[1].Location = new(value.Y, 0); + _bounds[2].Location = new(_bounds[1].Size.X + _bounds[1].Location.X, 0); + } + _size = value; + } + } + public Vector2i Location { + get => _bounds[0].Location; + set + { + Vector2i diff = _bounds[0].Location - value; + for (int i = 0; i < _bounds.Length; i++) + { + _bounds[i].Location -= diff; + } + if (_watermark.Visible && !string.IsNullOrEmpty(_watermark.Text)) + { + _watermark.Location = TextLocation switch + { + TextLocation.TrueCenterLeft => new(value.X + Border + 5, value.Y + ((Size.Y - _watermark.TrueHeight) / 2) - (_watermark.Size.Y - _watermark.TrueHeight)), + TextLocation.PostiveTureCenterLeft => new(value.X + Border + 5, value.Y + ((Size.Y - _label.PostiveTrueHeight) / 2) - _label.Size.Y + _label.TrueHeight), + TextLocation.PxLeft => new(value.X + Border + 5, value.Y + ((Size.Y - _watermark.Size.Y) / 2)), + _ => new(value.X + Border + 5, value.Y + Border + 5) + }; + _label.Location = _watermark.Location; + } + else + { + _label.Location = TextLocation switch + { + TextLocation.TrueCenterLeft => new(value.X + Border + 5, value.Y + ((Size.Y - _label.TrueHeight) / 2) - (_label.Size.Y - _label.TrueHeight)), + TextLocation.PostiveTureCenterLeft => new(value.X + Border + 5, value.Y + ((Size.Y - _label.PostiveTrueHeight) / 2) - _label.Size.Y + _label.TrueHeight), + TextLocation.PxLeft => new(value.X + Border + 5, value.Y + ((Size.Y - _label.Size.Y) / 2)), + _ => new(value.X + Border + 5, value.Y + Border + 5) + }; + _watermark.Location = _label.Location; + } + } + } + + public Vector2 SizeAsFloat { get; } = new(); + public Vector2 LocationAsFloat { get => _bounds[0].LocationAsFloat; } + public Vector2i Distance { get; set; } + public IParent? Parent { get; private set; } + public Window? Window { get; private set; } + public Color4 TextColor { get => _label.Color; set => _label.Color = value; } + public Color4 WatermarkColor { get => _watermark.Color; set => _watermark.Color = value; } + + public bool Visible + { + get => _bounds[0].Visible; + set + { + if (value == _bounds[0].Visible) return; + for (int i = 0; i < _bounds.Length; i++) + { + _bounds[i].Visible = value; + } + if (value) + { + if (!string.IsNullOrEmpty(_label.Text)) + { + _label.Visible = true; + _watermark.Visible = false; + } + else + { + _label.Visible = false; + _watermark.Visible = true; + } + } + else + { + _label.Visible = value; + _watermark.Visible = value; + } + } + } + public event Func? Clicked; + + public void Clean() + { + for (int i = 0; i < _bounds.Length; i++) + { + _bounds[i].Clean(); + } + _label.Clean(); + _watermark.Clean(); + } + + //private Vector2i? l, s; + + public void Draw(int x, int y, int w, int h) + { + if (!Visible || !Loaded) return; + for (int i = 0; i < _bounds.Length; i++) + { + _bounds[i].Draw(x,y,w,h); + } + int nx = x, ny = y, nw = w, nh = h; + if (Location.X + Border > nw) + return; + else + { + nx += (Location.X + Border); + nw -= (Location.X + Border); + if (Size.X - Border < nw) + nw = Size.X - Border; + } + + if (Location.Y + Border > nh) + return; + else + { + ny += (Location.Y + Border); + nh -= (Location.Y + Border); + if (Size.Y - Border < nh) + nh = Size.Y - Border; + } + if (nh < 1 || nw < 1) return; + GL.Scissor(nx,ny,nw,nh); + if (!string.IsNullOrEmpty(_label.Text)) _label.Draw(nx,ny,nw,nh); + else _watermark.Draw(nx,ny,nw,nh); + } + + public void LoadToParent(IParent parent, Window window) + { + if (Loaded) return; + Parent = parent; + Window = window; + Window.MouseDown += Window_MouseDown; + Window.KeyDown += Window_KeyDown; + Window.TextInput += WindowOnTextInput; + Loaded = true; + if (!Window!.Context.IsCurrent) Window.Context.MakeCurrent(); + for (int i = 0; i < _bounds.Length; i++) + { + _bounds[i].LoadToParent(Parent, Window); + } + _label.LoadToParent(Parent, Window); + _watermark.LoadToParent(Parent, Window); + Window.MouseMove += WindowOnMouseMove; + Location = Location; + if (WindowLoaded is not null) WindowLoaded.Invoke(this); + } + + private void WindowOnTextInput(TextInputEventArgs obj) + { + if (!use) return; + Text += obj.AsString; + } + + private bool use; + public event Func? KeyPress; + + public void UnFocus() + { + use = false; + if (Window is not null && Window.focused == this) + Window.focused = null; + } + public void Focus() + { + if (Window is not null) + { + if (Window.focused is not null) + { + Window.focused.UnFocus(); + } + + Window.focused = this; + use = true; + } + } + private void Window_KeyDown(KeyboardKeyEventArgs obj) + { + if (!use) return; + if (obj.Key == Keys.CapsLock || obj.Key == Keys.Menu || obj.Key == Keys.LeftSuper || obj.Key == Keys.RightSuper || obj.Key == Keys.End || obj.Key == Keys.Home || obj.Key == Keys.PageDown || obj.Key == Keys.PageUp || obj.Key == Keys.Insert || obj.Key == Keys.Up || obj.Key == Keys.Down || obj.Key == Keys.Left || obj.Key == Keys.Right) return; + if (obj.Key == Keys.Backspace || obj.Key == Keys.Delete) + { + if (!(Text.Length > 0)) return; + Text = Text.Remove(Text.Length - 1, 1); + } + + if (obj.Key == Keys.V && obj.Control && Window is not null) Text += Window.ClipboardString; + if (KeyPress is not null) _ = KeyPress.Invoke(obj); + } + + private void Window_MouseDown(MouseButtonEventArgs e) + { + if (Visible && + e.Button == MouseButton.Button1 && + Parent?.IntToFloat(Location.X) <= Window?.IntToFloat((int)Window?.MousePosition.X!) && + Parent?.IntToFloat(Size.X + Location.X) >= Window?.IntToFloat((int)Window?.MousePosition.X!) && + Parent?.IntToFloat(Location.Y + Size.Y, true) <= Window?.IntToFloat((int)Window?.MousePosition.Y!, true) && + Parent?.IntToFloat(Location.Y, true) >= Window?.IntToFloat((int)Window?.MousePosition.Y!, true)) + { + use = true; + Focus(); + if (Clicked is not null) Clicked.Invoke(this); + } + else use = false; + } +} diff --git a/GraphicsManager/Objects/UserControl.cs b/GraphicsManager/Objects/UserControl.cs index fbcb67f..f75bb08 100755 --- a/GraphicsManager/Objects/UserControl.cs +++ b/GraphicsManager/Objects/UserControl.cs @@ -4,6 +4,7 @@ using GraphicsManager.Objects.Core; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; using OpenTK.Windowing.Common; +using OpenTK.Windowing.Common.Input; namespace GraphicsManager.Objects; @@ -19,6 +20,19 @@ public class UserControl : IRenderObject, IParent _bounds.MouseLeave += BoundsOnMouseLeave; } + public MouseCursor HoverMouse + { + get => _bounds.HoverMouse; + set + { + _bounds.HoverMouse = value; + for (int i = 0; i < Controls.Length; i++) + { + if (Controls[i].HoverMouse == MouseCursor.Default) Controls[i].HoverMouse = value; + } + } + } + public void TryDraw() { if (!BlockDraw && Parent is not null) Parent.TryDraw(); @@ -65,8 +79,13 @@ public class UserControl : IRenderObject, IParent { BlockDraw = true; _bounds.Size = value; - ParentResize(new()); - if (Parent is not null) Parent.TryDraw(); + + if (Parent is not null) + { + if (Loaded) ParentResize(new(Parent.Size)); + Parent.TryDraw(); + } + else ParentResize(new()); BlockDraw = false; } } @@ -93,11 +112,23 @@ public class UserControl : IRenderObject, IParent BlockDraw = false; } } - public Vector2i ScissorLocation { get => _bounds.ScissorLocation; } + + public void ForceDistanceUpdate() + { + if (Parent is null) return; + ForceDistanceUpdate(Parent); + } + + public void ForceDistanceUpdate(IParent parent) + { + _bounds.ForceDistanceUpdate(parent); + } + + //public Vector2i ScissorLocation { get => _bounds.ScissorLocation; } public Vector2i Position => Location; public Vector2 LocationAsFloat { get => _bounds.LocationAsFloat; } - public Vector2i Distance { get => _bounds.Distance; } + public Vector2i Distance { get => _bounds.Distance; set => _bounds.Distance = value; } public event Func? Clicked; public event Func? WindowLoaded; public event Func? MouseEnter; @@ -125,11 +156,46 @@ public class UserControl : IRenderObject, IParent if (WindowLoaded is not null) WindowLoaded.Invoke(this); } + public bool dw; + public void Draw(int x, int y, int w, int h) { if (Loaded) { - _bounds.Draw(x,y,w,h); + int nx = x, ny = y, nw = w, nh = h; + if (Location.X > nw) + return; + else + { + nx += Location.X; + nw -= Location.X; + if (Size.X < nw) + nw = Size.X; + } + + if (Location.Y > nh) + return; + else + { + ny += Location.Y; + nh -= Location.Y; + if (Size.Y < nh) + nh = Size.Y; + } + if (dw) Console.WriteLine("UserControl\nLoc: {0}\nSize: {1}\n\nX: {2}\nY: {3}\nW: {4}\nH:{5}\n\nX: {6}\nY: {7}\nW: {8}\nH:{9}", + Location, + Size, + x, + y, + w, + h, + nx, + ny, + nw, + nh); + if (nw == 0 || nh == 0) return; + GL.Scissor(nx, Window!.Size.Y - ny - nh, nw, nh); + _bounds.Draw(nx,ny,nw,nh); IEnumerable needload = Controls.Where(a => a.Loaded == false); @@ -145,25 +211,15 @@ public class UserControl : IRenderObject, IParent } for (int i = 0; i < Controls.Length; i++) { - Vector2i laff = new(Controls[i].ScissorLocation.X, Controls[i].ScissorLocation.Y); - Vector2i saff = new Vector2i(Controls[i].Size.X, Controls[i].Size.Y); - if (laff.X < ScissorLocation.X) laff = new(ScissorLocation.X, laff.Y); - if (laff.X < x) laff = new(x, laff.Y); - if (laff.Y < ScissorLocation.Y) laff = new(laff.X, ScissorLocation.Y); - if (laff.Y < y) laff = new(laff.X, y); - if (saff.X + laff.X > Size.X + ScissorLocation.X) saff = new(Size.X, saff.Y); - if (saff.Y + laff.Y > Size.Y + ScissorLocation.Y) saff = new(saff.X, Size.Y); - GL.Scissor(laff.X, laff.Y, saff.X, saff.Y); - Controls[i].Draw(ScissorLocation.X, ScissorLocation.Y, Size.X, Size.Y); + if (Controls[i] is not IParent) + { + GL.Scissor(nx, Window!.Size.Y - ny - nh, nw, nh); + } + Controls[i].Draw(nx, ny, nw, nh); } } } - public Vector2i GetParentRelLocPoint() - { - return Parent!.GetParentRelLocPoint() + new Vector2i(Location.X, Parent.Size.Y - (Location.Y + Size.Y)); - } - public void Clean() { for (int i = 0; i < Controls.Length; i++) diff --git a/GraphicsManager/Resources/Shaders/AlphaChannel.frag b/GraphicsManager/Resources/Shaders/AlphaChannel.frag new file mode 100755 index 0000000..7d8fbd2 --- /dev/null +++ b/GraphicsManager/Resources/Shaders/AlphaChannel.frag @@ -0,0 +1,13 @@ +#version 330 +out vec4 outputColor; + +in vec4 vertexColor; +in vec2 texCoord; + +uniform sampler2D texture1; + +void main(void) +{ + float obj = texture(texture1, texCoord).r; + outputColor = vec4(vertexColor.r, vertexColor.g, vertexColor.b, vertexColor.a*obj); +} \ No newline at end of file diff --git a/GraphicsManager/Resources/Shaders/AlphaChannel.vert b/GraphicsManager/Resources/Shaders/AlphaChannel.vert new file mode 100755 index 0000000..b436dab --- /dev/null +++ b/GraphicsManager/Resources/Shaders/AlphaChannel.vert @@ -0,0 +1,12 @@ +#version 330 +layout(location = 0) in vec3 aPosition; +layout(location = 1) in vec2 aTexCoord; +out vec2 texCoord; +out vec4 vertexColor; +uniform vec4 objColor; +void main(void) +{ + texCoord = aTexCoord; + gl_Position = vec4(aPosition, 1.0); + vertexColor = objColor; +} \ No newline at end of file diff --git a/GraphicsManager/Resources/Shaders/AlphaChannelTexture.frag b/GraphicsManager/Resources/Shaders/AlphaChannelTexture.frag new file mode 100755 index 0000000..ba4c6ee --- /dev/null +++ b/GraphicsManager/Resources/Shaders/AlphaChannelTexture.frag @@ -0,0 +1,14 @@ +#version 460 +out vec4 outputColor; + +in vec2 texCoord; + +layout(binding = 0) uniform sampler2D texture1; +layout(binding = 1) uniform sampler2D texture2; + +void main(void) +{ + float obj = texture(texture1, texCoord).r; + vec4 text = texture(texture2, texCoord); + outputColor = vec4(text.r, text.g, text.b, text.a*obj); +} \ No newline at end of file diff --git a/GraphicsManager/Resources/Shaders/AlphaChannelTexture.vert b/GraphicsManager/Resources/Shaders/AlphaChannelTexture.vert new file mode 100755 index 0000000..d5a61d1 --- /dev/null +++ b/GraphicsManager/Resources/Shaders/AlphaChannelTexture.vert @@ -0,0 +1,9 @@ +#version 460 +layout(location = 0) in vec3 aPosition; +layout(location = 1) in vec2 aTexCoord; +out vec2 texCoord; +void main(void) +{ + texCoord = aTexCoord; + gl_Position = vec4(aPosition, 1.0); +} \ No newline at end of file diff --git a/GraphicsManager/Resources/Textures/Missing.png b/GraphicsManager/Resources/Textures/Missing.png new file mode 100644 index 0000000000000000000000000000000000000000..ccac7805aca5c3d48e6dfb6a5547ed1e98379064 GIT binary patch literal 98 zcmeAS@N?(olHy`uVBq!ia0vp^Od!m`1|*BN@u~nRmSQK*5Dp-y;YjHK@+Cc8978x} svL4*X$iTpHSmDqAhdH8r-b)hsEgrDlpA;Zh0aV1`>FVdQ&MBb@0CC0^p8x;= literal 0 HcmV?d00001 diff --git a/GraphicsManager/Structs/Character.cs b/GraphicsManager/Structs/Character.cs index 2325118..1312d4c 100755 --- a/GraphicsManager/Structs/Character.cs +++ b/GraphicsManager/Structs/Character.cs @@ -9,4 +9,5 @@ public struct Character public Vector2 Size { get; set; } public Vector2 Bearing { get; set; } public int Advance { get; set; } + public double AdvanceY { get; set; } } diff --git a/GraphicsManager/Tools.cs b/GraphicsManager/Tools.cs index ce3dad6..50cde9c 100755 --- a/GraphicsManager/Tools.cs +++ b/GraphicsManager/Tools.cs @@ -1,9 +1,61 @@ -using System.Reflection; +using System.Diagnostics; +using System.Reflection; namespace GraphicsManager; public class Tools { + public static void AddFontsToList(ref List List, string folder) + { + DirectoryInfo di = new(folder); + foreach (FileInfo file in di.GetFiles()) + { + if (!file.FullName.EndsWith(".otf") && !file.FullName.EndsWith(".ttf")) continue; + + List.Add(file.FullName); + } + foreach (DirectoryInfo direc in di.GetDirectories()) + { + AddFontsToList(ref List, direc.FullName); + } + } + + public static string[] GetFamilyList(string Command) + { + Process proc = new() + { + StartInfo = new() + { + FileName = "/bin/bash", + Arguments = $"-c \"{Command}\"", + RedirectStandardOutput = true, + } + }; + proc.Start(); + proc.WaitForExit(); + List bbb = proc.StandardOutput.ReadToEnd().Split($"{Environment.NewLine}").ToList(); + bbb.RemoveAt(bbb.Count - 1); + return bbb.ToArray(); + } + + public static string[] GetFontList(string Command) + { + Process proc = new() + { + StartInfo = new() + { + FileName = "/bin/bash", + Arguments = $"-c \"{Command}\"", + RedirectStandardOutput = true, + } + }; + proc.Start(); + proc.WaitForExit(); + List bbb = proc.StandardOutput.ReadToEnd().Split($": {Environment.NewLine}").ToList(); + bbb.RemoveAt(bbb.Count - 1); + return bbb.ToArray(); + } + public static byte[] GetResourceBytes(Assembly Assembly, string Resource) { Stream str = Assembly.GetManifestResourceStream(Resource)!; @@ -14,6 +66,12 @@ public class Tools ms.Dispose(); return result; } + + public static Stream GetResourceStream(Assembly Assembly, string Resource) + { + Stream str = Assembly.GetManifestResourceStream(Resource)!; + return str; + } public static string GetResourceString(Assembly Assembly, string Resource) { @@ -25,6 +83,8 @@ public class Tools return result; } + public static Stream GetResourceStream(string Resource) => GetResourceStream(typeof(Tools).Assembly, Resource); + public static byte[] GetResourceBytes(string Resource) => GetResourceBytes(typeof(Tools).Assembly, Resource); public static string GetResourceString(string Resource) => GetResourceString(typeof(Tools).Assembly, Resource); diff --git a/GraphicsManager/Window.cs b/GraphicsManager/Window.cs index bd12fd1..f798a9c 100755 --- a/GraphicsManager/Window.cs +++ b/GraphicsManager/Window.cs @@ -6,6 +6,7 @@ using GraphicsManager.Objects.Core; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; using OpenTK.Windowing.Common; +using OpenTK.Windowing.Common.Input; using OpenTK.Windowing.Desktop; using OpenTK.Windowing.GraphicsLibraryFramework; @@ -32,6 +33,7 @@ public class Window : NativeWindow , IParent } internal IRenderObject? focused; + public IRenderObject? CurrentTop { get; set;} public void CenterWindow(int mon) { Box2i clientArea = Monitors.GetMonitors()[mon].ClientArea; @@ -52,46 +54,66 @@ public class Window : NativeWindow , IParent internal ContextMenu? ActiveMenu { get; set; } = null; public IParent? Parent { get; } = null; + public MouseCursor HoverMouse { get; set; } = MouseCursor.Default; public Vector2 LocationAsFloat { get; } = new Vector2(0f, 0f); public Window(NativeWindowSettings nativeWindowSettings) : base(nativeWindowSettings) { TextureManager = TextureManager.GetTextureManager(Context); Context.MakeCurrent(); - if (!Texture.TextureShader.ContainsKey(Context)) Texture.TextureShader.Add(Context, new("RectangleTexture", true)); + if (!Texture.TextureShader.ContainsKey(Context)) Texture.TextureShader.Add(Context, new("RectangleTexture", true, Texture:true)); if (!Rectangle.DefaultShader.ContainsKey(Context)) Rectangle.DefaultShader.Add(Context, new("Rectangle", true)); + if (!Rectangle.DefaultAlphaShader.ContainsKey(Context)) Rectangle.DefaultAlphaShader.Add(Context, new("AlphaChannel", true, Texture:true)); + if (!Rectangle.DefaultAlphaTextureShader.ContainsKey(Context)) Rectangle.DefaultAlphaTextureShader.Add(Context, new("AlphaChannelTexture", true, Texture:true)); if (!Label.DefaultTextShader.ContainsKey(Context)) Label.DefaultTextShader.Add(Context, new("Label", true)); if (!Label._characters.ContainsKey(Context)) Label._characters.Add(Context, new()); last = WindowState; KeyDown += OnKeyDownn; } - -private WindowState last; -private bool fs = false; -private Vector2i os, loc; -private unsafe void OnKeyDownn(KeyboardKeyEventArgs obj) -{ - if (obj.Key != Keys.F11 || WindowBorder == WindowBorder.Fixed) return; - GLFW.WindowHint(WindowHintBool.AutoIconify, true); - if (WindowState != WindowState.Normal) last = WindowState; - Console.WriteLine(fs); - switch (fs) + + private WindowState last; + private bool fs = false; + private Vector2i os, loc; + public bool CustomF11 = true; + private unsafe void OnKeyDownn(KeyboardKeyEventArgs obj) { - case false: - loc = Location; - os = Size; - WindowBorder = WindowBorder.Hidden; - Location = new(4090, 0); - fs = true; - break; - case true: - WindowBorder = WindowBorder.Resizable; - - Size = os; - Location = loc; - fs = false; - break; + if (obj.Key != Keys.F11 || WindowBorder == WindowBorder.Fixed) return; + if (CustomF11) + { + GLFW.WindowHint(WindowHintBool.AutoIconify, true); + if (WindowState != WindowState.Normal) last = WindowState; + switch (fs) + { + case false: + loc = Location; + os = Size; + WindowBorder = WindowBorder.Hidden; + Location = new(4090, 0); + fs = true; + break; + case true: + WindowBorder = WindowBorder.Resizable; + GLFW.RestoreWindow(this.WindowPtr); + Size = os; + Location = loc; + fs = false; + break; + } + } + else + { + switch (fs) + { + case false: + WindowState = WindowState.Fullscreen; + fs = true; + break; + case true: + WindowState = WindowState.Normal; + fs = false; + break; + } + } } -} public Window() : this(new NativeWindowSettings()) { @@ -186,35 +208,39 @@ private unsafe void OnKeyDownn(KeyboardKeyEventArgs obj) } #endregion + public void ForceUpdate(ResizeEventArgs e) + { + BlockDraw = true; + 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); + } + } + DrawFrame(); + BlockDraw = false; + } + public void ParentResize(ResizeEventArgs e) { base.OnResize(e); if (e.Width == 0 && e.Height == 0 && WindowState != WindowState.Fullscreen) return; - BlockDraw = true; - GL.Viewport(0, 0, e.Width, e.Height); - 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); - } - } - DrawFrame(); - BlockDraw = false; + ForceUpdate(e); } private int frame = 0; @@ -307,19 +333,17 @@ private unsafe void OnKeyDownn(KeyboardKeyEventArgs obj) { invokes.Enqueue(A); } - - public Vector2i GetParentRelLocPoint() - { - return new(0); - } public void DrawFrame() { Context.MakeCurrent(); frame++; Console.WriteLine($"Drawing Frame: {frame}"); + GL.Enable(EnableCap.Blend); + GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.Enable(EnableCap.ScissorTest); - GL.Scissor(0, 0, Size.X, Size.Y); + GL.ClearColor(BackgroundColor.R, BackgroundColor.G, BackgroundColor.B, (BackgroundColor.A * -1) + 1); IEnumerable needload = Controls.Where(a => a.Loaded == false); @@ -337,21 +361,9 @@ private unsafe void OnKeyDownn(KeyboardKeyEventArgs obj) for (int i = 0; i < Controls.Length; i++) { if (!Controls[i].Loaded) continue; - GL.Disable(EnableCap.ScissorTest); - if (Controls[i] is not Label) - { - GL.Enable(EnableCap.ScissorTest); - GL.Scissor(Controls[i].ScissorLocation.X, Controls[i].ScissorLocation.Y, Controls[i].Size.X, Controls[i].Size.Y); - Controls[i].Draw(0,0,Size.X, Size.Y); - } - else - { - GL.Enable(EnableCap.ScissorTest); - GL.Scissor(0, 0, Size.X, Size.Y); - Controls[i].Draw(0,0,Size.X, Size.Y); - } + GL.Scissor(0, 0, Size.X, Size.Y); + Controls[i].Draw(0,0,Size.X, Size.Y); } - GL.Disable(EnableCap.ScissorTest); Context.SwapBuffers(); }