Rendering Optimizations

This commit is contained in:
JacobTech 2024-08-27 10:52:50 -04:00
parent 3595cfc27d
commit ec6d6064b1
22 changed files with 1413 additions and 1646 deletions

View File

@ -205,7 +205,7 @@ public class FPSWindow : GameWindow , IWindow
}
#endregion
public void ForceUpdate(ResizeEventArgs e)
public void ForceUpdate()
{
BlockDraw = true;
for (int i = 0; i < Controls.Length; i++)
@ -225,19 +225,15 @@ public class FPSWindow : GameWindow , IWindow
Controls[i].Location = new(lx, ly, Controls[i].Location.Z);
if (Controls[i] is IParent parent)
{
parent.ParentResize(e);
parent.ParentResize();
}
}
BlockDraw = false;
}
public void ParentResize(ResizeEventArgs e)
public void ParentResize()
{
base.OnResize(e);
if (e.Width == 0 && e.Height == 0 && WindowState != WindowState.Fullscreen) return;
GL.Viewport(0, 0, e.Width, e.Height);
Matrix4.CreateOrthographicOffCenter(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);
ForceUpdate(e);
ForceUpdate();
}
private int frame = 0;
@ -249,7 +245,11 @@ public class FPSWindow : GameWindow , IWindow
protected override void OnResize(ResizeEventArgs e)
{
ParentResize(e);
base.OnResize(e);
if (e.Width == 0 && e.Height == 0 && WindowState != WindowState.Fullscreen) return;
GL.Viewport(0, 0, e.Width, e.Height);
Matrix4.CreateOrthographicOffCenter(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);
ParentResize();
}
protected override void OnClosing(CancelEventArgs e)
@ -400,7 +400,7 @@ public class FPSWindow : GameWindow , IWindow
{
if (!Controls[i].Loaded) continue;
GL.Scissor(0, 0, Size.X, Size.Y);
Controls[i].Draw(0,0,Size.X, Size.Y);
Controls[i].Draw(0,0,0,0,Size.X, Size.Y);
}
Context.SwapBuffers();
base.OnRenderFrame(args);

View File

@ -10,7 +10,7 @@
<IncludeSymbols>False</IncludeSymbols>
<RepositoryUrl>https://git.jacobtech.com/JacobTech.com/GraphicsManager</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Version>1.0.9-alpha83</Version>
<Version>1.1.0-alpha50</Version>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

View File

@ -11,7 +11,7 @@ public interface IParent
public ControlList Controls { get; }
public IParent? Parent { get; }
public Vector2i Size { get; }
public void ParentResize(ResizeEventArgs e);
public void ParentResize();
public float IntToWindow(float p, bool Y = false);
public void TryDraw();
public void ReportSizeUpdate(IRenderObject Control);

View File

@ -1,5 +1,6 @@
using GraphicsManager.Enums;
using GraphicsManager.Objects;
using GraphicsManager.Objects.Core;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Common.Input;
@ -17,13 +18,19 @@ public interface IRenderObject
public bool AllowHoverFromBehind { get; set; }
public bool Loaded { get; }
public void LoadToParent(IParent Parent, IWindow Window);
public void Draw(int x, int y, int w, int h);
public void Draw(int x, int y, int sx, int sy, int sw, int sh);
public MouseCursor HoverMouse { get; set; }
public void SetSize(int wh);
public void SetSize(int w, int h);
public void SetLocation(int xy);
public void SetLocation(int x, int y);
public void SetLocation(int x, int y, int z);
public void Clean();
public void Focus();
public void UnFocus();
public void SendKeyEvent(KeyboardKeyEventArgs KeyArgs);
public void SendClipEvent(string Text);
public void SendFilesEvent(string[] Files);
public Vector2i Size { get; set; }
public Vector3i Location { get; set; }
public Vector2 SizeAsFloat { get; }
@ -33,9 +40,11 @@ public interface IRenderObject
public IWindow? Window { get; }
public bool Visible { get; set; }
public object? Tag { get; set; }
public List<SubHitBox> SubHitBoxes { get; }
public event Func<IRenderObject, Task>? Clicked;
public event Func<IRenderObject, Task>? MouseLeave;
public event Func<IRenderObject, string[], Task>? FilesDroped;
public event Func<IRenderObject, Task>? MouseEnter;
public event Func<IRenderObject, Task>? SizeChanged;
public event Func<IRenderObject, Task>? WindowLoaded;

View File

@ -18,8 +18,9 @@ public class ControlList
public int Length => _internal.Count;
internal event Func<int, IRenderObject, Task>? ControlAdded;
internal event Func<Task>? ControlRemoved;
public event Func<int, IRenderObject, Task>? ControlAdded;
public event Func<int, IRenderObject, Task>? ControlAfterAdded;
public event Func<Task>? ControlRemoved;
public void Remove(IRenderObject item, bool purge = true)
{
@ -43,12 +44,14 @@ public class ControlList
{
if (ControlAdded is not null) ControlAdded.Invoke(_internal.Count, item).Wait();
_internal.Add(item);
if (ControlAfterAdded is not null) ControlAfterAdded.Invoke(_internal.Count-1, item).Wait();
}
public void Insert(int index, IRenderObject item)
{
if (ControlAdded is not null) ControlAdded.Invoke(index, item).Wait();
_internal.Insert(index, item);
if (ControlAfterAdded is not null) ControlAfterAdded.Invoke(index, item).Wait();
}
public void Clear(bool purge = true)

View File

@ -39,4 +39,12 @@ public class Font
fontclass.Face = new Face(lib, Font.ToArray(), 0);
return fontclass;
}
internal static Font MakeFontFromByteArray(byte[] Font)
{
_ = Font ?? throw new ArgumentNullException(nameof(Font));
Font fontclass = new Font();
fontclass.Face = new Face(lib, Font, 0);
return fontclass;
}
}

View File

@ -9,13 +9,15 @@ public class FontFamily
{
private static uint index = 0;
public event Func<Task>? ReloadUI;
public static bool MemoryFont;
public static string FontPath = Path.GetTempPath();
public required string Family { get; init; }
private FontSize fs = FontSize.Thin;
internal Dictionary<FontSize, Tuple<string, Font?>> InternalFonts = new();
internal Dictionary<FontSize, Tuple<string, Font?>> InternalFontsi = new();
internal bool IsZip = false;
internal Dictionary<FontSize, Tuple<MemoryStream, Font?>> SInternalFonts = new();
internal Dictionary<FontSize, Tuple<MemoryStream, Font?>> SInternalFontsi = new();
//internal Dictionary<FontSize, Font> InternalFonts = new();
//internal Dictionary<FontSize, Font> InternalFontsi = new();
//internal bool IsZip = false;
internal Dictionary<FontSize, Font> InternalFonts = new();
internal Dictionary<FontSize, Font> InternalFontsi = new();
internal static List<FontFamily> AllFams = new();
public static Task<FontFamily> LoadFontFamilyTask(Stream FamilyZip, string Family, string extra = "-")
@ -32,7 +34,6 @@ public class FontFamily
};
AllFams.Add(f);
using ZipArchive archive = new ZipArchive(FamilyZip, ZipArchiveMode.Read, false);
f.IsZip = true;
foreach (ZipArchiveEntry font in archive.Entries)
{
@ -42,20 +43,57 @@ public class FontFamily
void tryadd(FontSize s, bool i = false)
{
var memoryStream = new MemoryStream();
var ss = font.Open();
if (MemoryFont)
{
using (var ss = font.Open())
{
using (var memoryStream = new MemoryStream())
{
ss.CopyTo(memoryStream);
byte[] fontBytes = memoryStream.ToArray();
if (i)
{
if (!f.SInternalFontsi.ContainsKey(s))
f.SInternalFontsi.Add(s, new(memoryStream, null));
if (!f.InternalFontsi.ContainsKey(s))
{
f.InternalFontsi.Add(s, Font.MakeFontFromByteArray(fontBytes));
}
}
else
{
if (!f.SInternalFonts.ContainsKey(s))
f.SInternalFonts.Add(s, new(memoryStream, null));
if (!f.InternalFonts.ContainsKey(s))
{
f.InternalFonts.Add(s, Font.MakeFontFromByteArray(fontBytes));
}
}
}
}
}
else
{
string p = FontPath;
if (!Directory.Exists(p)) Directory.CreateDirectory(p);
p = Path.Combine(p, "GM_Familys");
if (!Directory.Exists(p)) Directory.CreateDirectory(p);
p = Path.Combine(p, Family);
if (!Directory.Exists(p)) Directory.CreateDirectory(p);
p = Path.Combine(p, Path.GetRandomFileName());
font.ExtractToFile(p, true);
if (i)
{
if (!f.InternalFontsi.ContainsKey(s))
{
f.InternalFontsi.Add(s, Font.MakeFontFromFile(p));
}
}
else
{
if (!f.InternalFonts.ContainsKey(s))
{
f.InternalFonts.Add(s, Font.MakeFontFromFile(p));
}
}
}
ss.Dispose();
}
if (fd.EndsWith("italic"))

View File

@ -72,112 +72,26 @@ public class FontInteraction
{
CurrentFonts = new Font[Families_.Count];
for (int j = 0; j < Families_.Count; j++)
{
if (Families_[j].IsZip)
{
if (value)
{
if (Families_[j].SInternalFontsi.TryGetValue(FontSize, out Tuple<MemoryStream, Font?>? f))
if (Families_[j].InternalFontsi.TryGetValue(FontSize, out Font? f))
{
i = value;
if (f.Item2 is null)
{
switch (Italic)
{
case true:
Families_[j].SInternalFontsi[fs] = new(f.Item1,
Font.MakeFontFromStream(Families_[j].SInternalFontsi[fs].Item1));
break;
case false:
Families_[j].SInternalFonts[fs] = new(f.Item1,
Font.MakeFontFromStream(Families_[j].SInternalFonts[fs].Item1));
break;
}
}
CurrentFonts[j] = (Families_[j].SInternalFontsi[fs].Item2!);
CurrentFonts[j] = (Families_[j].InternalFontsi[fs]);
if (ReloadUI is not null) ReloadUI.Invoke();
}
}
else
{
if (Families_[j].SInternalFonts.TryGetValue(FontSize, out Tuple<MemoryStream, Font?>? f))
if (Families_[j].InternalFonts.TryGetValue(FontSize, out Font? f))
{
i = value;
if (f.Item2 is null)
{
switch (Italic)
{
case true:
Families_[j].SInternalFontsi[fs] = new(f.Item1,
Font.MakeFontFromStream(Families_[j].SInternalFontsi[fs].Item1));
Families_[j].SInternalFontsi[fs].Item1.Dispose();
break;
case false:
Families_[j].SInternalFonts[fs] = new(f.Item1,
Font.MakeFontFromStream(Families_[j].SInternalFonts[fs].Item1));
Families_[j].SInternalFonts[fs].Item1.Dispose();
break;
}
}
CurrentFonts[j] = Families_[j].SInternalFonts[fs].Item2!;
CurrentFonts[j] = Families_[j].InternalFonts[fs];
if (ReloadUI is not null) ReloadUI.Invoke();
}
}
}
else
{
if (value)
{
if (Families_[j].InternalFontsi.TryGetValue(FontSize, out Tuple<string, Font?>? f))
{
i = value;
if (f.Item2 is null)
{
switch (Italic)
{
case true:
Families_[j].InternalFontsi[fs] = new(f.Item1,
Font.MakeFontFromFile(Families_[j].InternalFontsi[fs].Item1));
break;
case false:
Families_[j].InternalFonts[fs] = new(f.Item1,
Font.MakeFontFromFile(Families_[j].InternalFonts[fs].Item1));
break;
}
}
CurrentFonts[j] = (Families_[j].InternalFontsi[fs].Item2!);
if (ReloadUI is not null) ReloadUI.Invoke();
}
}
else
{
if (Families_[j].InternalFonts.TryGetValue(FontSize, out Tuple<string, Font?>? f))
{
i = value;
if (f.Item2 is null)
{
switch (Italic)
{
case true:
Families_[j].InternalFontsi[fs] = new(f.Item1,
Font.MakeFontFromFile(Families_[j].InternalFontsi[fs].Item1));
break;
case false:
Families_[j].InternalFonts[fs] = new(f.Item1,
Font.MakeFontFromFile(Families_[j].InternalFonts[fs].Item1));
break;
}
}
CurrentFonts[j] = Families_[j].InternalFonts[fs].Item2!;
if (ReloadUI is not null) ReloadUI.Invoke();
}
}
}
}
}
}
}
@ -185,9 +99,7 @@ public class FontInteraction
private static Tuple<string, Font?> gcl(Dictionary<FontSize, Tuple<string, Font?>> thisList, FontSize thisValue, out FontSize fs)
{
Dictionary<FontSize, Tuple<string, Font?>>.KeyCollection keys = thisList.Keys;
FontSize nearest = thisValue -
keys.Where(k => k <= thisValue)
.Min(k => thisValue - k);
FontSize nearest = keys.OrderBy(k => Math.Abs(k - thisValue)).First();
fs = nearest;
return thisList[nearest];
}
@ -195,9 +107,15 @@ public class FontInteraction
private static Tuple<MemoryStream, Font?> Sgcl(Dictionary<FontSize, Tuple<MemoryStream, Font?>> thisList, FontSize thisValue, out FontSize fs)
{
Dictionary<FontSize, Tuple<MemoryStream, Font?>>.KeyCollection keys = thisList.Keys;
FontSize nearest = thisValue -
keys.Where(k => k <= thisValue)
.Min(k => thisValue - k);
FontSize nearest = keys.OrderBy(k => Math.Abs(k - thisValue)).First();
fs = nearest;
return thisList[nearest];
}
private static Font Sgcl(Dictionary<FontSize, Font> thisList, FontSize thisValue, out FontSize fs)
{
Dictionary<FontSize, Font>.KeyCollection keys = thisList.Keys;
FontSize nearest = keys.OrderBy(k => Math.Abs(k - thisValue)).First();
fs = nearest;
return thisList[nearest];
}
@ -210,62 +128,18 @@ public class FontInteraction
CurrentFonts = new Font[Families_.Count];
for (int j = 0; j < Families_.Count; j++)
{
if (Families_[j].IsZip)
Font f = Italic switch
{
Tuple<MemoryStream, Font?> f = Italic switch
{
true => Sgcl(Families_[j].SInternalFontsi, value, out fs),
false => Sgcl(Families_[j].SInternalFonts, value, out fs),
true => Sgcl(Families_[j].InternalFontsi, value, out fs),
false => Sgcl(Families_[j].InternalFonts, value, out fs),
};
if (f.Item2 is null)
{
switch (Italic)
{
case true:
Families_[j].SInternalFontsi[fs] = new(f.Item1, Font.MakeFontFromStream(Families_[j].SInternalFontsi[fs].Item1));
Families_[j].SInternalFontsi[fs].Item1.Dispose();
break;
case false:
Families_[j].SInternalFonts[fs] = new(f.Item1, Font.MakeFontFromStream(Families_[j].SInternalFonts[fs].Item1));
Families_[j].SInternalFonts[fs].Item1.Dispose();
break;
}
}
CurrentFonts[j] = Italic switch
{
true => Families_[j].SInternalFontsi[fs].Item2!,
false => Families_[j].SInternalFonts[fs].Item2!,
true => Families_[j].InternalFontsi[fs],
false => Families_[j].InternalFonts[fs],
};
}
else
{
Tuple<string, Font?> f = Italic switch
{
true => gcl(Families_[j].InternalFontsi, value, out fs),
false => gcl(Families_[j].InternalFonts, value, out fs),
};
if (f.Item2 is null)
{
switch (Italic)
{
case true:
Families_[j].InternalFontsi[fs] = new(f.Item1,
Font.MakeFontFromFile(Families_[j].InternalFontsi[fs].Item1));
break;
case false:
Families_[j].InternalFonts[fs] =
new(f.Item1, Font.MakeFontFromFile(Families_[j].InternalFonts[fs].Item1));
break;
}
}
CurrentFonts[j] = Italic switch
{
true => Families_[j].InternalFontsi[fs].Item2!,
false => Families_[j].InternalFonts[fs].Item2!,
};
}
}
if (ReloadUI is not null) ReloadUI.Invoke();
}
}

View File

@ -0,0 +1,623 @@
using System.Text;
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
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;
namespace GraphicsManager.Objects.Core;
public class LabelBase : ILabel
{
public LabelBase(FontFamily fontFamily)
{
Font = FontInteraction.Load(fontFamily);
}
public LabelBase(FontInteraction interaction)
{
Font = interaction;
}
public BetterContextMenu? ContextMenu { get; set; } = null;
public IParent? Parent { get; protected set; }
public ObjectAnchor Anchor { get; set; } = ObjectAnchor.Left | ObjectAnchor.Top;
protected Vector2 laf = new(), saf = new();
public Vector2 LocationAsFloat { get { return laf; } }
public Vector2 SizeAsFloat { get { return saf; } }
protected Vector2i? msize = null;
public virtual Vector2i? MaxSize
{
get => msize;
set
{
msize = value;
StringBuilder sb = new();
float max_x = 0, lines = 1, char_x = 0F;
for (int i = 0; i < Text.Length; i++)
{
char c;
if (PasswordChar is null)
c = Text[i];
else
c = PasswordChar.Value;
bool n = (c == '\n');
if (n)
{
lines++;
sb.Append(c);
char_x = 0f;
}
else
{
Character ch;
if (Window is not null) ch = Texture.GetChar(Font, c, Window.Context);
else ch = Texture.GetChar(Font, c);
if (i > 0 && text[i-1] == ' ')
{
int addc = 0;
float word_char_x = char_x;
while (MaxSize is not null)
{
if (addc + i == Text.Length) break;
if (text[addc + i] == ' ') break;
Character ch2;
if (Window is not null) ch2 = Texture.GetChar(Font, text[addc + i], Window.Context);
else ch2 = Texture.GetChar(Font, c);
word_char_x += (ch2.Advance >> 6) * Scale;
if (word_char_x > MaxSize.Value.X)
{
char_x = 0f;
lines++;
sb.Append('\n');
break;
}
addc++;
}
}
sb.Append(c);
float w = ch.Size.X * Scale;
float xrel = char_x + ch.Bearing.X * Scale;
char_x += (ch.Advance >> 6) * Scale;
if ((xrel + w) >= max_x) max_x = (xrel + w);
}
}
text_Calculated = sb.ToString();
Size = new((int)max_x, (int)(lines * LineHeight) + (int)(lines * Font.ExtraLinePixels));
}
}
protected char? pc;
public char? PasswordChar
{
get => pc;
set
{
pc = value;
if (Parent is not null) Parent.TryDraw();
}
}
protected bool _Visible = true;
public virtual bool Visible
{
get => _Visible;
set
{
_Visible = value;
if (Parent is not null && Loaded) Parent.TryDraw();
}
}
public static readonly Dictionary<IGLFWGraphicsContext, Dictionary<FontInteraction, Dictionary<uint, Character>>> _characters = new();
protected string text = string.Empty;
protected string text_Calculated = string.Empty;
public int VAO { get; protected set; }
public virtual void Focus()
{
}
public virtual void UnFocus()
{
}
public int VBO { get; protected set; }
public virtual Vector2 DIR { get; set; } = new Vector2(1f, 0f);
public virtual Vector2i GetSizeOfChar(int Index)
{
float mx = 0, my = 0;
char character;
if (PasswordChar is null)
character = Text[Index];
else
character = PasswordChar.Value;
if (character == '\n')
{
mx = 0f;
my += Font.PixelHeight * Scale;
}
else
{
Character cha;
if (Window is not null) cha = Texture.GetChar(Font, character, Window.Context);
else cha = Texture.GetChar(Font, character);
mx = cha.Size.X * Scale;
my = cha.Size.Y * Scale;
}
return new((int)mx, (int)my);
}
public virtual Vector2i GetBearingOfChar(int Index)
{
float mx = 0, my = 0;
char character;
if (PasswordChar is null)
character = Text[Index];
else
character = PasswordChar.Value;
if (character == '\n')
{
mx = 0f;
my += Font.PixelHeight * Scale;
}
else
{
Character cha;
if (Window is not null) cha = Texture.GetChar(Font, character, Window.Context);
else cha = Texture.GetChar(Font, character);
mx = cha.Bearing.X * Scale;
my = cha.Bearing.Y * Scale;
}
return new((int)mx, (int)my);
}
public List<SubHitBox> SubHitBoxes { get; } = new();
public virtual string Text
{
get => text;
set
{
if (value is null) value = string.Empty;
text = value;
StringBuilder sb = new();
text_Calculated = string.Empty;
float max_x = 0, lines = 1, char_x = 0F;
for (int i = 0; i < Text.Length; i++)
{
char c;
if (PasswordChar is null)
c = Text[i];
else
c = PasswordChar.Value;
bool n = (c == '\n');
if (n)
{
lines++;
char_x = 0f;
sb.Append(c);
}
else
{
Character ch;
if (Window is not null) ch = Texture.GetChar(Font, c, Window.Context);
else ch = Texture.GetChar(Font, c);
if (MaxSize is not null && i > 0 && text[i-1] == ' ')
{
int addc = 0;
float word_char_x = char_x;
while (true)
{
if (addc + i == Text.Length) break;
if (text[addc + i] == ' ') break;
Character ch2;
if (Window is not null) ch2 = Texture.GetChar(Font, text[addc + i], Window.Context);
else ch2 = Texture.GetChar(Font, c);
word_char_x += (ch2.Advance >> 6) * Scale;
if (word_char_x > MaxSize.Value.X)
{
char_x = 0f;
lines++;
sb.Append('\n');
break;
}
addc++;
}
}
sb.Append(c);
float w = ch.Size.X * Scale;
float xrel = char_x + ch.Bearing.X * Scale;
char_x += (ch.Advance >> 6) * Scale;
if ((xrel + w) >= max_x) max_x = (xrel + w);
}
}
text_Calculated = sb.ToString();
Size = new((int)max_x, (int)(lines * LineHeight) + (int)(lines * Font.ExtraLinePixels));
if (Loaded)
{
if (Window is not null && Window.CanControleUpdate)
{
if (!Window.Context.IsCurrent)
{
try
{
Window.Context.MakeCurrent();
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
if (Window.Context.IsCurrent)
{
Parent!.TryDraw();
}
}
}
}
}
public virtual uint LineHeight
{
get
{
return (uint)((Font.PixelHeight * (Font.CurrentFonts[0].Face.Height / (float)Font.CurrentFonts[0].Face.UnitsPerEM)) * Scale);
}
}
public Shader Shader { get; set; } = null!;
public FontInteraction Font { get; protected set; }
public virtual float Scale { get; set; } = 1.0f;
public virtual Vector2i Distance { get; set; }
protected Vector3i loc_;
public virtual Vector3i Location
{
get
{
return loc_;
}
set
{
SetLocation(value.X, value.Y, value.Z);
}
}
public virtual void SetLocation(int xy)
{
SetLocation(xy, xy, 0);
}
public virtual void SetLocation(int x, int y)
{
SetLocation(x, y, 0);
}
public virtual void SetLocation(int x, int y, int z)
{
loc_.X = x;
loc_.Y = y;
loc_.Z = z;
if (Window is null || Parent is null) return;
if (Window.CanControleUpdate && Loaded)
{
Parent!.TryDraw();
if (!Window.Context.IsCurrent) Window.Context.MakeCurrent();
}
}
public virtual void SetSize(int wh)
{
SetSize(wh, wh);
}
public virtual void SetSize(int w, int h)
{
_size.X = w;
_size.Y = h;
}
protected Vector2i _size;
public virtual 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 virtual Vector2i GetCharLocation(int index)
{
float max_x = 0, lines = 0, char_x = 0F;
for (int i = 0; i < index; i++)
{
char c;
if (PasswordChar is null)
c = text_Calculated[i];
else
c = PasswordChar.Value;
bool n = (c == '\n');
if (n)
{
lines++;
char_x = 0f;
}
else
{
Character ch;
if (Window is not null) ch = Texture.GetChar(Font, c, Window.Context);
else ch = Texture.GetChar(Font, c);
float w = ch.Size.X * Scale;
float xrel = char_x + ch.Bearing.X * Scale;
char_x += (ch.Advance >> 6) * Scale;
max_x = (xrel + w);
}
}
return new((int)char_x, (int)(lines * LineHeight) + (int)(lines * Font.ExtraLinePixels));
}
public virtual void SendKeyEvent(KeyboardKeyEventArgs KeyArgs)
{
}
public virtual void SendClipEvent(string ClipString)
{
}
public virtual void Clean()
{
Tuple<int, int, int> 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 event Func<IRenderObject, Task>? SizeChanged;
public virtual void Draw(int x, int y, int sx, int sy, int sw, int sh)
{
if (Visible && Loaded && this.Font is not null)
{
if (!Window!.Context.IsCurrent) Window.Context.MakeCurrent();
Shader.Use();
GL.Uniform4(Shader.GetUniformLocation("textColor"), new Color4(255,255,255,255));
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
Shader.SetMatrixF4("projection", Window.WindowSizeMatrix);
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 + Parent!.IntToWindow(0), loc_.Y + (Font.PixelHeight * Scale) + Parent!.IntToWindow(0, true), 0f));
float char_x = 0.0f;
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
GL.ActiveTexture((Shader.GetUniformLocation("u_texture") switch
{
0 => TextureUnit.Texture0,
1 => TextureUnit.Texture1,
2 => TextureUnit.Texture2,
3 => TextureUnit.Texture3,
4 => TextureUnit.Texture4,
5 => TextureUnit.Texture5,
6 => TextureUnit.Texture6,
7 => TextureUnit.Texture7,
8 => TextureUnit.Texture8,
9 => TextureUnit.Texture9,
}));
float hhh = 0f;
for (int i = 0; i < text_Calculated.Length; i++)
{
char c;
if (PasswordChar is null)
c = text_Calculated[i];
else
c = PasswordChar.Value;
bool n = (c == '\n');
if (!_characters[Window!.Context][Font].ContainsKey(c) && !n)
{
_ = Texture.TextureForChar(Window!.Context, Font, c, Shader);
}
if (n)
{
hhh += LineHeight;
hhh += Font.ExtraLinePixels;
char_x = 0f;
}
else
{
if (!_characters[Window!.Context][Font].ContainsKey(c)) continue;
Character ch = _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 virtual void ForceDistanceUpdate()
{
}
public virtual void ForceDistanceUpdate(IParent parent)
{
if (parent is IWindow w) Distance = new(w.CS.X - Size.X - Location.X, w.CS.Y - Size.Y - Location.Y);
else Distance = new(parent.Size.X - Size.X - Location.X, parent.Size.Y - Size.Y - Location.Y);
}
public IWindow? Window { get; protected set; }
protected static Dictionary<IGLFWGraphicsContext, Tuple<int, int, int>> GlobalBuffers = new();
public bool IgnoreHover { get; set; }
public bool AllowHoverFromBehind { get; set; }
public event Func<IRenderObject, string[], Task>? FilesDroped;
public void SendFilesEvent(string[] Files)
{
if (FilesDroped is not null) _ = FilesDroped.Invoke(this, Files);
}
public virtual void LoadToParent(IParent window, IWindow win)
{
if (Loaded) return;
if (!_characters.ContainsKey(win!.Context)) _characters.Add(win!.Context, new());
if (!_characters[win!.Context].ContainsKey(Font)) _characters[win!.Context].Add(Font, new Dictionary<uint, Character>());
if (Shader is null) Shader = Label.DefaultTextShader[win.Context];
Parent = window;
Window = win;
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<int, int, int> tup = GlobalBuffers[win.Context];
VBO = tup.Item1;
VAO = tup.Item2;
GlobalBuffers[win.Context] = new(VBO, VAO, tup.Item3 + 1);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindVertexArray(0);
Loaded = true;
Text = Text;
Location = Location;
if (Distance.X == 0 && Distance.Y == 0) ForceDistanceUpdate(Parent);
if (WindowLoaded is not null) WindowLoaded.Invoke(this);
}
private void WindowOnMouseDown(MouseButtonEventArgs obj)
{
if (MouseInside && obj.Button == MouseButton.Button1)
{
bool subnothit = true;
if (SubHitBoxes.Count > 0)
{
foreach (SubHitBox hb in SubHitBoxes)
{
if (hb.MouseInside)
{
hb.SendClick();
subnothit = false;
}
}
}
if (subnothit && Clicked is not null) _ = Clicked.Invoke(this);
}
if (MouseInside && obj.Button == MouseButton.Button2 && ContextMenu is not null && Window!.HoveringControl == this) ContextMenu.ShowContext(Window!);
if (obj.Button != MouseButton.Button2 && ContextMenu is not null && ContextMenu.Visible) ContextMenu.HideContext(Window!);
}
public MouseCursor HoverMouse { get; set; } = MouseCursor.Default;
protected bool mi;
public virtual bool MouseInside
{
get => mi;
set
{
if (Window is null) return;
if (Window.HoveringControl == this && value)
{
mi = value;
if (MouseEnter is not null) MouseEnter.Invoke(this);
}
if (Window.HoveringControl != this && !value)
{
mi = value;
if (MouseLeave is not null) MouseLeave.Invoke(this);
}
}
}
public event Func<IRenderObject, Task>? Clicked;
public event Func<IRenderObject, Task>? WindowLoaded;
public event Func<IRenderObject, Task>? MouseEnter;
public event Func<IRenderObject, Task>? MouseLeave;
public object? Tag { get; set; } = null;
private bool l = false;
protected virtual void InvokeWindowLoaded()
{
if (WindowLoaded is not null) WindowLoaded.Invoke(this);
}
public bool Loaded
{
get => l;
protected set
{
l = value;
}
}
}

View File

@ -24,11 +24,9 @@ public abstract class ParentBase : Rectangle, IParent
if (!BlockDraw && Parent is not null) Parent.TryDraw();
}
public virtual void ParentResize(ResizeEventArgs e)
public virtual void ParentResize()
{
bool PastBlockState = BlockDraw;
BlockDraw = true;
if (e.Width == 0 && e.Height == 0) return;
for (int i = 0; i < Controls.Length; i++)
{
if (!Controls[i].Loaded) continue;
@ -42,15 +40,24 @@ public abstract class ParentBase : Rectangle, IParent
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, Controls[i].Location.Z);
if (Controls[i] is IParent parent)
bool mooved = false;
if (sx != Controls[i].Size.X || sy != Controls[i].Size.Y)
{
parent.ParentResize(e);
mooved = true;
Controls[i].SetSize(sx, sy);
}
if (lx != Controls[i].Location.X || ly != Controls[i].Location.Y)
{
mooved = true;
Controls[i].SetLocation(lx, ly);
}
if (mooved && Controls[i] is IParent parent)
{
parent.ParentResize();
}
}
Parent!.TryDraw();
BlockDraw = PastBlockState;
if (Parent is not null) Parent.TryDraw();
BlockDraw = false;
}
public virtual void ReportSizeUpdate(IRenderObject Control)
@ -58,41 +65,45 @@ public abstract class ParentBase : Rectangle, IParent
}
public override void Draw(int x, int y, int w, int h)
public override void Draw(int x, int y, int sx, int sy, int sw, int sh)
{
if (Loaded && Visible && Location.X > 0 - Size.X && Location.Y > 0 - Size.Y)
{
int nx = x, ny = y, nw = w, nh = h;
if (Location.X > nw)
if (Location.X - sx + x > sw || Location.Y - sy + y > sh)
return;
if (Location.X - sx + x > -1)
{
int add = Location.X - sx + x;
sx += add;
sw -= add;
if (Size.X < sw)
sw = Size.X;
}
else
{
nx += Location.X;
nw -= Location.X;
if (Size.X < nw)
nw = Size.X;
if (Size.X + Location.X - sx + x < sw)
sw = Size.X + Location.X - sx + x;
}
if (Location.Y - sy + y > -1)
{
int add = Location.Y - sy + y;
sy += add;
sh -= add;
if (Size.Y < sh)
sh = Size.Y;
}
else
{
if (Size.Y + Location.Y - sy + y < sh)
sh = Size.Y + Location.Y - sy + y;
}
if (Location.Y > nh)
return;
else
{
if (Location.Y > -1)
{
ny += Location.Y;
nh -= Location.Y;
if (Size.Y < nh)
nh = Size.Y;
}
else
{
if (Size.Y + Location.Y < nh)
nh = Size.Y + Location.Y;
}
}
if (nw == 0 || nh == 0) return;
GL.Scissor(nx, Window!.CS.Y - ny - nh, nw, nh);
base.Draw(nx,ny,nw,nh);
x += Location.X;
y += Location.Y;
if (sw <= 0 || sh <= 0) return;
base.Draw(x,y,sx,sy,sw,sh);
IEnumerable<IRenderObject> needload = Controls.Where(a => a.Loaded == false);
if (needload.Any())
@ -108,8 +119,8 @@ public abstract class ParentBase : Rectangle, IParent
for (int i = 0; i < Controls.Length; i++)
{
if (Controls[i].Location.X > Size.X || Controls[i].Location.Y > Size.Y) continue;
GL.Scissor(nx, Window!.CS.Y - ny - nh, nw, nh);
Controls[i].Draw(nx, ny, nw, nh);
GL.Scissor(sx, Window!.CS.Y - sy - sh, sw, sh);
Controls[i].Draw(x,y,sx,sy,sw,sh);
}
}
}
@ -149,7 +160,7 @@ public abstract class ParentBase : Rectangle, IParent
{
Controls[i].Location = Controls[i].Location;
}
ParentResize(new());
ParentResize();
if (Parent is not null) Parent.TryDraw();
BlockDraw = false;
}

View File

@ -60,11 +60,11 @@ public class RoundedButton : Rectangle
base.Clean();
}
public override void Draw(int x, int y, int w, int h)
public override void Draw(int x, int y, int sx, int sy, int sw, int sh)
{
if (!Visible || !Loaded) return;
base.Draw(x,y,w,h);
_label.Draw(x,y,w,h);
base.Draw(x,y,sx,sy,sw,sh);
_label.Draw(x,y,sx,sy,sw,sh);
}
public override void LoadToParent(IParent Parent, IWindow Window)

View File

@ -115,6 +115,12 @@ public class Shader : IDisposable
GL.UniformMatrix4(_uniformLocations[name], true, ref data);
}
public void SetMatrix4(int loc, Matrix4 data)
{
GL.UseProgram(Handle);
GL.UniformMatrix4(loc, true, ref data);
}
public void SetMatrixF4(string name, Matrix4 data)
{
GL.UseProgram(Handle);

View File

@ -0,0 +1,41 @@
using OpenTK.Mathematics;
using OpenTK.Windowing.Common.Input;
namespace GraphicsManager.Objects.Core;
public class SubHitBox
{
public virtual Vector2i Size { get; set; }
public virtual Vector2i Location { get; set; }
public virtual MouseCursor HoverMouse { get; set; } = MouseCursor.Default;
private bool mi = false;
internal virtual bool MouseInside
{
get
{
return mi;
}
set
{
if (mi == value) return;
mi = value;
if (value && MouseEnter is not null) MouseEnter.Invoke(this).Wait();
if (!value && MouseLeave is not null) MouseLeave.Invoke(this).Wait();
}
}
public event Func<SubHitBox, Task>? Clicked;
public event Func<SubHitBox, Task>? MouseLeave;
public event Func<SubHitBox, Task>? MouseEnter;
internal void SendClick()
{
if (Clicked is not null) _ = Clicked.Invoke(this);
}
public override string ToString()
{
return base.ToString()+ $": {{X: {Location.X}, Y: {Location.Y}, Width: {Size.X}, Height: {Size.Y}}}";
}
}

View File

@ -146,7 +146,7 @@ public class Texture
{
}
internal static Character GetChar(Face face, char charter)
public static Character GetChar(Face face, char charter)
{
ushort temp = (charter);
if (face.GetCharIndex(temp) == 0)
@ -172,7 +172,7 @@ public class Texture
};
}
internal static Character GetChar(FontInteraction l, char charter, IGLFWGraphicsContext con)
public static Character GetChar(FontInteraction l, char charter, IGLFWGraphicsContext con)
{
try
{
@ -203,7 +203,7 @@ public class Texture
return GetChar(l.CurrentFonts[0].Face, (char)1);
}
internal static Character GetChar(FontInteraction l, char charter)
public static Character GetChar(FontInteraction l, char charter)
{
try
{
@ -235,7 +235,7 @@ public class Texture
private static Dictionary<FontInteraction, Texture> BadChars = new();
internal static Texture TextureForChar(IGLFWGraphicsContext con, FontInteraction l, char charter, Shader s)
public static Texture TextureForChar(IGLFWGraphicsContext con, FontInteraction l, char charter, Shader s)
{
try
{

View File

@ -200,20 +200,25 @@ public class FlowLayout : ParentBase, IFlow
return Task.CompletedTask;
}
public override void SetSize(int w, int h)
{
BlockDraw = true;
base.SetSize(w, h);
for (int i = 0; i < Controls.Length; i++)
{
Controls[i].SetSize(w, Controls[i].Size.Y);
}
ParentResize();
if (Parent is not null) Parent.TryDraw();
BlockDraw = false;
}
public override Vector2i Size
{
get => base.Size;
set
{
BlockDraw = true;
base.Size = value;
for (int i = 0; i < Controls.Length; i++)
{
Controls[i].Size = new(value.X, Controls[i].Size.Y);
}
ParentResize(new());
if (Parent is not null) Parent.TryDraw();
BlockDraw = false;
SetSize(value.X, value.Y);
}
}

View File

@ -1,4 +1,5 @@
using GraphicsManager.Enums;
using System.Text;
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using GraphicsManager.Objects.Core;
using GraphicsManager.Structs;
@ -11,353 +12,27 @@ using OpenTK.Windowing.GraphicsLibraryFramework;
namespace GraphicsManager.Objects;
public class Label : ILabel
public class Label : LabelBase
{
public static readonly Dictionary<IGLFWGraphicsContext, Shader> DefaultTextShader = new();
public Label(FontFamily fontFamily)
public Label(FontFamily fontFamily):base(fontFamily)
{
Font = FontInteraction.Load(fontFamily);
}
public Label(FontInteraction interaction)
public Label(FontInteraction interaction):base(interaction)
{
Font = interaction;
}
public BetterContextMenu? 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 Vector2i? msize = null;
public Vector2i? MaxSize
{
get => msize;
set
{
msize = value;
text_Calculated = string.Empty;
float max_x = 0, lines = 1, char_x = 0F;
for (int i = 0; i < Text.Length; i++)
{
char c;
if (PasswordChar is null)
c = Text[i];
else
c = PasswordChar.Value;
bool n = (c == '\n');
if (n)
{
lines++;
text_Calculated += c;
char_x = 0f;
}
else
{
Character ch;
if (Window is not null) ch = Texture.GetChar(Font, c, Window.Context);
else ch = Texture.GetChar(Font, c);
if (i > 0 && text[i-1] == ' ')
{
int addc = 0;
float word_char_x = char_x;
while (MaxSize is not null)
{
if (addc + i == Text.Length) break;
if (text[addc + i] == ' ') break;
Character ch2;
if (Window is not null) ch2 = Texture.GetChar(Font, text[addc + i], Window.Context);
else ch2 = Texture.GetChar(Font, c);
word_char_x += (ch2.Advance >> 6) * Scale;
if (word_char_x > MaxSize.Value.X)
{
char_x = 0f;
lines++;
text_Calculated += '\n';
break;
}
addc++;
}
}
text_Calculated += c;
float w = ch.Size.X * Scale;
float xrel = char_x + ch.Bearing.X * Scale;
char_x += (ch.Advance >> 6) * Scale;
if ((xrel + w) >= max_x) max_x = (xrel + w);
}
}
Size = new((int)max_x, (int)(lines * LineHeight) + (int)(lines * Font.ExtraLinePixels));
}
}
private char? pc;
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();
}
}
public static readonly Dictionary<IGLFWGraphicsContext, Dictionary<FontInteraction, Dictionary<uint, Character>>> _characters = new();
private string text = string.Empty;
private string text_Calculated = 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 Vector2i GetSizeOfChar(int Index)
{
float mx = 0, my = 0;
char character;
if (PasswordChar is null)
character = Text[Index];
else
character = PasswordChar.Value;
if (character == '\n')
{
mx = 0f;
my += Font.PixelHeight * Scale;
}
else
{
Character cha;
if (Window is not null) cha = Texture.GetChar(Font, character, Window.Context);
else cha = Texture.GetChar(Font, character);
mx = cha.Size.X * Scale;
my = cha.Size.Y * Scale;
}
return new((int)mx, (int)my);
}
public string Text
{
get => text;
set
{
if (value is null) value = string.Empty;
text = value;
text_Calculated = string.Empty;
float max_x = 0, lines = 1, char_x = 0F;
for (int i = 0; i < Text.Length; i++)
{
char c;
if (PasswordChar is null)
c = Text[i];
else
c = PasswordChar.Value;
bool n = (c == '\n');
if (n)
{
lines++;
char_x = 0f;
text_Calculated += c;
}
else
{
Character ch;
if (Window is not null) ch = Texture.GetChar(Font, c, Window.Context);
else ch = Texture.GetChar(Font, c);
if (MaxSize is not null && i > 0 && text[i-1] == ' ')
{
int addc = 0;
float word_char_x = char_x;
while (true)
{
if (addc + i == Text.Length) break;
if (text[addc + i] == ' ') break;
Character ch2;
if (Window is not null) ch2 = Texture.GetChar(Font, text[addc + i], Window.Context);
else ch2 = Texture.GetChar(Font, c);
word_char_x += (ch2.Advance >> 6) * Scale;
if (word_char_x > MaxSize.Value.X)
{
char_x = 0f;
lines++;
text_Calculated += '\n';
break;
}
addc++;
}
}
text_Calculated += c;
float w = ch.Size.X * Scale;
float xrel = char_x + ch.Bearing.X * Scale;
char_x += (ch.Advance >> 6) * Scale;
if ((xrel + w) >= max_x) max_x = (xrel + w);
}
}
Size = new((int)max_x, (int)(lines * LineHeight) + (int)(lines * Font.ExtraLinePixels));
if (Loaded)
{
if (Window is not null && Window.CanControleUpdate)
{
if (!Window.Context.IsCurrent)
{
try
{
Window.Context.MakeCurrent();
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
if (Window.Context.IsCurrent)
{
Parent!.TryDraw();
}
}
}
}
}
public uint LineHeight
{
get
{
return (uint)((Font.PixelHeight * (Font.CurrentFonts[0].Face.Height / (float)Font.CurrentFonts[0].Face.UnitsPerEM)) * Scale);
}
}
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 Vector3i loc_;
public Vector3i Location
{
get
{
return loc_;
}
set
{
loc_ = value;
if (Window is null || Parent is null) return;
if (Window.CanControleUpdate && Loaded)
{
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 Vector2i GetCharLocation(int index)
{
float max_x = 0, lines = 0, char_x = 0F;
for (int i = 0; i < index; i++)
{
char c;
if (PasswordChar is null)
c = text_Calculated[i];
else
c = PasswordChar.Value;
bool n = (c == '\n');
if (n)
{
lines++;
char_x = 0f;
}
else
{
Character ch;
if (Window is not null) ch = Texture.GetChar(Font, c, Window.Context);
else ch = Texture.GetChar(Font, c);
float w = ch.Size.X * Scale;
float xrel = char_x + ch.Bearing.X * Scale;
char_x += (ch.Advance >> 6) * Scale;
max_x = (xrel + w);
}
}
return new((int)char_x, (int)(lines * LineHeight) + (int)(lines * Font.ExtraLinePixels));
}
public virtual void SendKeyEvent(KeyboardKeyEventArgs KeyArgs)
{
}
public virtual void SendClipEvent(string ClipString)
{
}
public void Clean()
{
Tuple<int, int, int> 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 event Func<IRenderObject, Task>? SizeChanged;
public void Draw(int x, int y, int ww, int hh)
public override void Draw(int x, int y, int sx, int sy, int sw, int sh)
{
if (Visible && Loaded && this.Font is not null)
{
if (!Window!.Context.IsCurrent) Window.Context.MakeCurrent();
Shader.Use();
GL.Enable(EnableCap.Blend);
GL.Uniform4(Shader.GetUniformLocation("textColor"), Color);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
@ -429,106 +104,4 @@ public class Label : ILabel
}
}
}
public void ForceDistanceUpdate()
{
}
public void ForceDistanceUpdate(IParent parent)
{
Distance = new(parent.Size.X - Size.X - Location.X, parent.Size.Y - Size.Y - Location.Y);
}
public IWindow? Window { get; private set; }
private static Dictionary<IGLFWGraphicsContext, Tuple<int, int, int>> GlobalBuffers = new();
public bool IgnoreHover { get; set; }
public bool AllowHoverFromBehind { get; set; }
public void LoadToParent(IParent window, IWindow win)
{
if (Loaded) return;
if (!_characters.ContainsKey(win!.Context)) _characters.Add(win!.Context, new());
if (!_characters[win!.Context].ContainsKey(Font)) _characters[win!.Context].Add(Font, new Dictionary<uint, Character>());
if (Shader is null) Shader = DefaultTextShader[win.Context];
Parent = window;
Window = win;
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<int, int, int> tup = GlobalBuffers[win.Context];
VBO = tup.Item1;
VAO = tup.Item2;
GlobalBuffers[win.Context] = new(VBO, VAO, tup.Item3 + 1);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindVertexArray(0);
Loaded = true;
Text = Text;
Location = Location;
if (Distance.X == 0 && Distance.Y == 0) 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);
}
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 && Window!.HoveringControl == this) ContextMenu.ShowContext(Window!);
if (obj.Button != MouseButton.Button2 && ContextMenu is not null && ContextMenu.Visible) ContextMenu.HideContext(Window!);
}
public MouseCursor HoverMouse { get; set; } = MouseCursor.Default;
private bool mi;
public bool MouseInside
{
get => mi;
set
{
if (Window is null) return;
if (Window.HoveringControl == this && value)
{
mi = value;
if (MouseEnter is not null) MouseEnter.Invoke(this);
}
if (Window.HoveringControl != this && !value)
{
mi = value;
if (MouseLeave is not null) MouseLeave.Invoke(this);
}
}
}
public event Func<IRenderObject, Task>? Clicked;
public event Func<IRenderObject, Task>? WindowLoaded;
public event Func<IRenderObject, Task>? MouseEnter;
public event Func<IRenderObject, Task>? MouseLeave;
public object? Tag { get; set; } = null;
public bool Loaded { get; private set; }
}

View File

@ -146,10 +146,10 @@ public class ProgressBar : ParentBase
}
}
public override void Draw(int x, int y, int w, int h)
public override void Draw(int x, int y, int sx, int sy, int sw, int sh)
{
if (UpdateOnDraw) UpdateProgress();
base.Draw(x, y, w, h);
base.Draw(x, y, sx,sy, sw, sh);
}
public void UpdateProgress()

View File

@ -1,505 +0,0 @@
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 BetterContextMenu? 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, character);
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, character);
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 Vector3i loc_ = new();
private int maxy = 0, maxx = 0;
public Vector3i 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<int, int, int> 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 event Func<IRenderObject, Task>? SizeChanged;
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 + Parent!.IntToWindow(0), loc_.Y + (Font.PixelHeight * Scale) + Parent!.IntToWindow(0, true), 0f));
float char_x = 0.0f;
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
GL.ActiveTexture((Shader.GetUniformLocation("u_texture") switch
{
0 => TextureUnit.Texture0,
1 => TextureUnit.Texture1,
2 => TextureUnit.Texture2,
3 => TextureUnit.Texture3,
4 => TextureUnit.Texture4,
5 => TextureUnit.Texture5,
6 => TextureUnit.Texture6,
7 => TextureUnit.Texture7,
8 => TextureUnit.Texture8,
9 => TextureUnit.Texture9,
}));
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, Shader);
}
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 virtual void SendKeyEvent(KeyboardKeyEventArgs KeyArgs)
{
}
public virtual void SendClipEvent(string ClipString)
{
}
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 IWindow? Window { get; private set; }
private static Dictionary<IGLFWGraphicsContext, Tuple<int, int, int>> GlobalBuffers = new();
public void LoadToParent(IParent window, IWindow 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<uint, Character>());
if (Shader is null) Shader = Label.DefaultTextShader[win.Context];
Parent = window;
Window = win;
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<int, int, int> 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 && Window!.HoveringControl == this) ContextMenu.ShowContext(Window!);
if (obj.Button != MouseButton.Button2 && ContextMenu is not null && ContextMenu.Visible) ContextMenu.HideContext(Window!);
}
public MouseCursor HoverMouse { get; set; } = MouseCursor.Default;
private bool mi = false;
public bool MouseInside
{
get => mi;
set
{
if (Window is null) return;
if (Window.HoveringControl == this && value)
{
mi = value;
if (MouseEnter is not null) MouseEnter.Invoke(this);
}
if (Window.HoveringControl != this && !value)
{
mi = value;
if (MouseLeave is not null) MouseLeave.Invoke(this);
}
}
}
public bool AllowHoverFromBehind { get; set; }
public bool IgnoreHover { get; set; }
public event Func<IRenderObject, Task>? Clicked;
public event Func<IRenderObject, Task>? WindowLoaded;
public event Func<IRenderObject, Task>? MouseEnter;
public event Func<IRenderObject, Task>? MouseLeave;
public object? Tag { get; set; } = null;
public bool Loaded { get; private set; } = false;
}

View File

@ -5,6 +5,7 @@ using GraphicsManager.Interfaces;
using GraphicsManager.Objects.Core;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using OpenTK.Platform.Windows;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Common.Input;
using OpenTK.Windowing.Desktop;
@ -50,7 +51,6 @@ public class Rectangle : ITextureObject
public List<Texture> Textures { get; set; } = new();
public BetterContextMenu? ContextMenu { get; set; } = null;
public event Func<string[], Task>? FilesDroped;
public Rectangle(Texture? texture)
{
@ -92,7 +92,6 @@ public class Rectangle : ITextureObject
}
}
public Action? OnDrawAction;
public virtual void SendKeyEvent(KeyboardKeyEventArgs KeyArgs)
{
@ -102,23 +101,21 @@ public class Rectangle : ITextureObject
{
}
//public Action? OnDrawExitAction;
public virtual void Draw(int x, int y, int w, int h)
public virtual void Draw(int x, int y, int sx, int sy, int sw, int sh)
{
if (Visible && Loaded && Location.X > 0 - Size.X && Location.Y > 0 - Size.Y)
{
if (OnDrawAction is not null) OnDrawAction.Invoke();
if (!Window!.Context.IsCurrent) Window.Context.MakeCurrent();
foreach (Texture tex in Textures)
{
tex.Use();
}
Shader.Use();
Shader.SetMatrix4("windowMatrix", Window.WindowSizeMatrix);
Shader.SetMatrix4(Shader.GetUniformLocation("windowMatrix"), Window.WindowSizeMatrix);
if (!Textures.Any() || Shader.Handle == DefaultAlphaShader[Window!.Context].Handle)
{
GL.Uniform4(0, BackgroundColor);
GL.Uniform4(Shader.GetUniformLocation("objColor"), BackgroundColor);
}
GL.BindVertexArray(ArrayObject);
GL.DrawElements(PrimitiveType.Triangles, Indexs.Length, DrawElementsType.UnsignedShort, 0);
@ -126,6 +123,12 @@ public class Rectangle : ITextureObject
}
public virtual MouseCursor HoverMouse { get; set; } = MouseCursor.Default;
public List<SubHitBox> SubHitBoxes { get; } = new();
public event Func<IRenderObject, string[], Task>? FilesDroped;
public void SendFilesEvent(string[] Files)
{
if (FilesDroped is not null) _ = FilesDroped.Invoke(this, Files);
}
public void ForceDistanceUpdate()
{
@ -135,7 +138,8 @@ public class Rectangle : ITextureObject
public void ForceDistanceUpdate(IParent parent)
{
Distance = new(parent.Size.X - Size.X - Location.X, parent.Size.Y - Size.Y - Location.Y);
if (parent is IWindow w) Distance = new(w.CS.X - Size.X - Location.X, w.CS.Y - Size.Y - Location.Y);
else Distance = new(parent.Size.X - Size.X - Location.X, parent.Size.Y - Size.Y - Location.Y);
}
public virtual void Clean()
@ -168,8 +172,8 @@ public class Rectangle : ITextureObject
Loaded = true;
Window.MouseDown += Window_MouseDown;
Window.FileDrop += WindowOnFileDrop;
Location = Location;
if (Distance.X == 0 && Distance.Y == 0) Distance = new(Parent.Size.X - Size.X - Location.X, Parent.Size.Y - Size.Y - Location.Y);
SetLocation(loc_.X, loc_.Y, loc_.Z);
if (Distance.X == 0 && Distance.Y == 0) ForceDistanceUpdate(Parent);
if (WindowLoaded is not null) WindowLoaded.Invoke(this);
}
@ -187,7 +191,7 @@ public class Rectangle : ITextureObject
private void WindowOnFileDrop(FileDropEventArgs obj)
{
if (!MouseInside) return;
if (FilesDroped is not null) _ = FilesDroped.Invoke(obj.FileNames);
if (FilesDroped is not null) _ = FilesDroped.Invoke(this, obj.FileNames);
}
private bool mi = false;
@ -456,10 +460,20 @@ public class Rectangle : ITextureObject
}
set
{
size_ = value;
SetSize(value.X, value.Y);
}
}
public virtual void SetSize(int wh)
{
SetSize(wh, wh);
}
public virtual void SetSize(int w, int h)
{
size_.X = w;
size_.Y = h;
if (Window is null || Parent is null) return;
Parent.ReportSizeUpdate(this);
//float[] temp = Points;
float[] temp = Textures.Count == 0
? new float[12]
: TextureDisplay switch
@ -469,7 +483,8 @@ public class Rectangle : ITextureObject
TextureDisplay.Center => new float[80],
_ => new float[20]
};
saf = new Vector2(Parent.IntToWindow(value.X + loc_.X, false), Parent.IntToWindow(value.Y + loc_.Y, true));
saf.X = Parent.IntToWindow(w + loc_.X);
saf.Y = Parent.IntToWindow(h + loc_.Y, true);
temp[2] = Location.Z;
temp[(!Textures.Any() ? 5 : 7)] = Location.Z;
temp[(!Textures.Any() ? 8 : 12)] = Location.Z;
@ -486,17 +501,16 @@ public class Rectangle : ITextureObject
if (Textures.Count > 0)
{
Vector2i s = value;
float diff = Window.IntToWindow(s.Y) + 1;
float diff = Window.IntToWindow(h) + 1;
float per = (float)Textures[0].RawSize!.Value.Y / Textures[0].RawSize!.Value.X;
if (TextureDisplay == TextureDisplay.TextureHorizontalCenter)
diff = Window.IntToWindow(Textures[0].RawSize!.Value.Y);
if (TextureDisplay == TextureDisplay.Center)
{
if (s.X > Textures[0].RawSize!.Value.X)
if (w> Textures[0].RawSize!.Value.X)
diff = (Window.IntToWindow(Textures[0].RawSize!.Value.X) + 1) / 3;
else
diff = (Window.IntToWindow(s.X) + 1) / 3;
diff = (Window.IntToWindow(w) + 1) / 3;
per = Textures[0].MaxText.X / 3;
}
@ -544,14 +558,14 @@ public class Rectangle : ITextureObject
temp[19] = Textures[0].MaxText.Y;
int dy, dx;
if (s.Y > Textures[0].RawSize!.Value.Y)
if (h > Textures[0].RawSize!.Value.Y)
dy = Textures[0].RawSize!.Value.Y;
else
dy = s.Y;
if (s.X > Textures[0].RawSize!.Value.X)
dy = h;
if (w > Textures[0].RawSize!.Value.X)
dx = Textures[0].RawSize!.Value.X;
else
dx = s.X;
dx = w;
if (dy > dx) dy = dx;
else dx = dy;
@ -575,9 +589,9 @@ public class Rectangle : ITextureObject
SetPoint(temp, 75, temp[35], temp[21], temp[2], temp[38], temp[24]);
break;
case TextureDisplay.ProgressHorizontalCenter:
if (s.X > s.Y)
if (w > h)
{
if (s.X > s.Y + s.Y)
if (w > h+ h)
{
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
@ -609,7 +623,7 @@ public class Rectangle : ITextureObject
}
else
{
temp[3] = (0.666666f + (((s.X - s.Y) / (float)s.Y)* per)) * Textures[0].MaxText.X;
temp[3] = (0.666666f + (((w - h) / (float)h)* per)) * Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = temp[3];
temp[19] = Textures[0].MaxText.Y;
@ -642,7 +656,7 @@ public class Rectangle : ITextureObject
else
{
//first 33% of texture
temp[3] = ((s.X/(float)s.Y)*per);
temp[3] = ((w/(float)h)*per);
temp[4] = Textures[0].MaxText.Y;
temp[8] = temp[3];
temp[19] = Textures[0].MaxText.Y;
@ -675,19 +689,23 @@ public class Rectangle : ITextureObject
}
Points = temp;
temp = Array.Empty<float>();
if (SizeChanged is not null) SizeChanged.Invoke(this);
}
}
public virtual Vector3i Location
public virtual void SetLocation(int x, int y)
{
get
{
return loc_;
SetLocation(x, y, Location.Z);
}
set
public virtual void SetLocation(int xy)
{
loc_ = value;
SetLocation(xy, xy, 0);
}
public virtual void SetLocation(int x, int y, int z)
{
loc_.X = x;
loc_.Y = y;
loc_.Z = z;
if (Window is null || Parent is null) return;
float[] temp = Textures.Count == 0
? new float[12]
@ -698,17 +716,19 @@ public class Rectangle : ITextureObject
TextureDisplay.Center => new float[80],
_ => new float[20]
};
laf = new Vector2(Parent.IntToWindow(value.X, false), Parent.IntToWindow(value.Y, true));
temp[2] = value.Z;
temp[(!Textures.Any() ? 5 : 7)] = value.Z;
temp[(!Textures.Any() ? 8 : 12)] = value.Z;
temp[(!Textures.Any() ? 11 : 17)] = value.Z;
laf.X = Parent.IntToWindow(x);
laf.Y = Parent.IntToWindow(y, true);
temp[2] = z;
temp[(!Textures.Any() ? 5 : 7)] = z;
temp[(!Textures.Any() ? 8 : 12)] = z;
temp[(!Textures.Any() ? 11 : 17)] = z;
temp[(!Textures.Any() ? 6 : 10)] = laf.X;
temp[(!Textures.Any() ? 9 : 15)] = laf.X;
temp[1] = laf.Y;
temp[(!Textures.Any() ? 10 : 16)] = laf.Y;
saf = new Vector2(Parent.IntToWindow(Size.X + value.X, false), Parent.IntToWindow(Size.Y + value.Y, true));
saf.X = Parent.IntToWindow(Size.X + x);
saf.Y = Parent.IntToWindow(Size.Y + y, true);
temp[0] = saf.X;
temp[(!Textures.Any() ? 3 : 5)] = saf.X;
temp[(!Textures.Any() ? 4 : 6)] = saf.Y;
@ -898,6 +918,18 @@ public class Rectangle : ITextureObject
}
}
Points = temp;
temp = Array.Empty<float>();
}
public virtual Vector3i Location
{
get
{
return loc_;
}
set
{
SetLocation(value.X, value.Y, value.Z);
}
}

View File

@ -141,10 +141,9 @@ public class TabControl : ParentBase, IParent
}
}
public override void ParentResize(ResizeEventArgs e)
public override void ParentResize()
{
BlockDraw = true;
if (e.Width == 0 && e.Height == 0) return;
if (!(Controls.Length >= PageIndex)) return;
if (!Controls[PageIndex].Loaded) return;
bool top = (Controls[PageIndex].Anchor & ObjectAnchor.Top) == ObjectAnchor.Top;
@ -161,7 +160,7 @@ public class TabControl : ParentBase, IParent
Controls[PageIndex].Location = new(lx, ly, Controls[PageIndex].Location.Z);
if (Controls[PageIndex] is IParent parent)
{
parent.ParentResize(e);
parent.ParentResize();
}
for (int i = 0; i < Buttonts.Length; i++)
{
@ -180,7 +179,7 @@ public class TabControl : ParentBase, IParent
Buttonts[i].Location = new(lx, ly, Buttonts[i].Location.Z);
if (Buttonts[i] is IParent parent2)
{
parent2.ParentResize(e);
parent2.ParentResize();
}
}
Parent!.TryDraw();
@ -201,16 +200,16 @@ public class TabControl : ParentBase, IParent
BlockDraw = false;
}
public override void Draw(int x, int y, int w, int h)
public override void Draw(int x, int y, int sx, int sy, int sw, int sh)
{
if (Loaded && Visible)
{
base.Draw(x,y,w,h);
base.Draw(x,y,sx,sy,sw,sh);
if (!(Controls.Length >= (PageIndex))) return;
if (!Controls[PageIndex].Loaded) return;
Controls[PageIndex].Draw(x,y,w,h);
Controls[PageIndex].Draw(x,y,sx,sy,sw,sh);
for (int i = 0; i < Buttonts.Length; i++)
Buttonts[i].Draw(x,y,w,h);
Buttonts[i].Draw(x,y,sx,sy,sw,sh);
}
}

View File

@ -1,7 +1,7 @@
#version 330
in vec2 in_pos;
in vec2 in_uv;
layout (location = 0) in vec2 in_pos;
layout (location = 1) in vec2 in_uv;
out vec2 vUV;

View File

@ -77,6 +77,14 @@ public class Window : NativeWindow , IWindow
WindowSizeMatrix = Matrix4.CreateOrthographicOffCenter(0.0f, Size.X, Size.Y, 0, 1, -1);
KeyDown += OnKeyDownn;
TextInput += OnTextInputEvent;
FileDrop += OnFileDrop;
GL.Enable(EnableCap.Blend);
GL.Enable(EnableCap.ScissorTest);
}
private void OnFileDrop(FileDropEventArgs obj)
{
}
private void OnTextInputEvent(TextInputEventArgs obj)
@ -136,28 +144,20 @@ public class Window : NativeWindow , IWindow
}
}
public Window() : this(new NativeWindowSettings())
{
/*
TextureManager = TextureManager.GetTextureManager(Context);
if (!Texture.TextureShader.ContainsKey(Context)) Texture.TextureShader.Add(Context, new("RectangleTexture", true));
if (!Rectangle.DefaultShader.ContainsKey(Context)) Rectangle.DefaultShader.Add(Context, new("Rectangle", true));
if (!Label.DefaultTextShader.ContainsKey(Context)) Label.DefaultTextShader.Add(Context, new("Label", true));
if (!Label._characters.ContainsKey(Context)) Label._characters.Add(Context, new());*/
}
public Window() : this(new NativeWindowSettings()) { }
public Vector3i Position { get; } = new(0);
public Color4 BackgroundColor { get; set; } = new Color4(0, 0, 0, 255);
public ControlList Controls { get; } = new();
public Vector2i CS { get; private set; } = new(0, 0);
public Vector2i CS { get; set; } = new(0, 0);
public float IntToWindow(float p, bool Y = false)
{
return p;
}
public void ForceUpdate(ResizeEventArgs e)
public virtual void ForceUpdate()
{
BlockDraw = true;
for (int i = 0; i < Controls.Length; i++)
@ -169,15 +169,15 @@ public class Window : NativeWindow , IWindow
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, Controls[i].Location.Z);
int lx = (left ? Controls[i].Location.X : CS.X - Controls[i].Distance.X - Controls[i].Size.X);
int ly = (top ? Controls[i].Location.Y : CS.Y - Controls[i].Distance.Y - Controls[i].Size.Y);
int sy = (bottom ? CS.Y - Controls[i].Distance.Y - ly : Controls[i].Size.Y);
int sx = (right ? CS.X - Controls[i].Distance.X - lx : Controls[i].Size.X);
Controls[i].SetSize(sx, sy);
Controls[i].SetLocation(lx, ly);
if (Controls[i] is IParent parent)
{
parent.ParentResize(e);
parent.ParentResize();
}
}
DrawFrame();
@ -186,15 +186,9 @@ public class Window : NativeWindow , IWindow
public Matrix4 WindowSizeMatrix { get; set; }
public void ParentResize(ResizeEventArgs e)
public virtual void ParentResize()
{
base.OnResize(e);
if (e.Width == 0 && e.Height == 0 && WindowState != WindowState.Fullscreen) return;
WindowSizeMatrix = Matrix4.CreateOrthographicOffCenter(0.0f, e.Width, e.Height, 0, 1, -1);
GL.Viewport(0, 0, e.Width, e.Height);
CS = e.Size;
ForceUpdate(e);
ForceUpdate();
}
private int frame = 0;
@ -204,9 +198,22 @@ public class Window : NativeWindow , IWindow
}
public void SetWindowSize(Vector2i s)
{
WindowSizeMatrix = Matrix4.CreateOrthographicOffCenter(0.0f, s.X, s.Y, 0, 1, -1);
GL.Viewport(0, 0, s.X, s.Y);
CS = s;
ClientSize = CS;
ParentResize();
}
protected override void OnResize(ResizeEventArgs e)
{
ParentResize(e);
base.OnResize(e);
WindowSizeMatrix = Matrix4.CreateOrthographicOffCenter(0.0f, e.Width, e.Height, 0, 1, -1);
GL.Viewport(0, 0, e.Width, e.Height);
CS = e.Size;
ParentResize();
}
protected override void OnClosing(CancelEventArgs e)
@ -233,7 +240,7 @@ public class Window : NativeWindow , IWindow
{
ProcessEvents(10);
}
public void StartRender()
public virtual void StartRender()
{
Context.MakeCurrent();
initthread = Thread.CurrentThread.ManagedThreadId;
@ -260,10 +267,12 @@ public class Window : NativeWindow , IWindow
}
public IRenderObject? HoveringControl { get; set; }
public SubHitBox? HoveringHitBox { get; set; }
private void WhenMouseMove(MouseMoveEventArgs obj)
{
IRenderObject? cb = null;
SubHitBox? cbhb = null;
IRenderObject? checkcontrol(IRenderObject render, int add_x = 0, int addy = 0, IRenderObject? CurrentBest = null)
{
void ClearHoverChain(IRenderObject ChainObject)
@ -276,7 +285,17 @@ public class Window : NativeWindow , IWindow
}
}
if (ChainObject.AllowHoverFromBehind) ChainObject.MouseInside = false;
if (ChainObject.AllowHoverFromBehind)
{
ChainObject.MouseInside = false;
if (ChainObject.SubHitBoxes.Count > 0)
{
foreach (SubHitBox shb in ChainObject.SubHitBoxes)
{
shb.MouseInside = false;
}
}
}
}
if (!render.Visible ||
@ -297,13 +316,35 @@ public class Window : NativeWindow , IWindow
CurrentBest = checkcontrol(p.Controls._internal[i], add_x + render.Location.X, addy + render.Location.Y, CurrentBest);
}
}
if (CurrentBest is null)
{
cbhb = null;
CurrentBest = render;
}
else
{
if (CurrentBest.Location.Z < render.Location.Z) CurrentBest = render;
if (CurrentBest.Location.Z < render.Location.Z)
{
cbhb = null;
CurrentBest = render;
}
}
if (render == CurrentBest && CurrentBest.SubHitBoxes.Count > 0)
{
foreach (SubHitBox hb in CurrentBest.SubHitBoxes)
{
if (render.Location.X + hb.Location.X + add_x > obj.X ||
render.Location.Y + hb.Location.Y + addy > obj.Y ||
render.Location.X + hb.Location.X + hb.Size.X + add_x < obj.X ||
render.Location.Y + hb.Location.Y + hb.Size.Y + addy < obj.Y)
{
continue;
}
cbhb = hb;
}
}
return CurrentBest;
@ -325,6 +366,19 @@ public class Window : NativeWindow , IWindow
else Cursor = HoverMouse;
if (old is not null) old.MouseInside = false;
}
if (cbhb != HoveringHitBox)
{
SubHitBox? old = HoveringHitBox;
HoveringHitBox = cbhb;
if (cbhb is not null)
{
cbhb.MouseInside = true;
Cursor = cbhb.HoverMouse;
}
else Cursor = HoverMouse;
if (old is not null) old.MouseInside = false;
}
}
public void StartRenderAsync()
@ -357,16 +411,13 @@ public class Window : NativeWindow , IWindow
invokes.Enqueue(A);
}
public void DrawFrame()
public virtual void DrawFrame()
{
Context.MakeCurrent();
frame++;
if (LogFrames) 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.ClearColor(BackgroundColor.R, BackgroundColor.G, BackgroundColor.B, BackgroundColor.A);
IEnumerable<IRenderObject> needload = Controls.Where(a => a.Loaded == false);
@ -385,9 +436,8 @@ public class Window : NativeWindow , IWindow
{
if (!Controls[i].Loaded) continue;
GL.Scissor(0, 0, CS.X, CS.Y);
Controls[i].Draw(0,0,CS.X, CS.Y);
Controls[i].Draw(0,0,0,0,CS.X, CS.Y);
}
Context.SwapBuffers();
}
}