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 #endregion
public void ForceUpdate(ResizeEventArgs e) public void ForceUpdate()
{ {
BlockDraw = true; BlockDraw = true;
for (int i = 0; i < Controls.Length; i++) 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); Controls[i].Location = new(lx, ly, Controls[i].Location.Z);
if (Controls[i] is IParent parent) if (Controls[i] is IParent parent)
{ {
parent.ParentResize(e); parent.ParentResize();
} }
} }
BlockDraw = false; BlockDraw = false;
} }
public void ParentResize(ResizeEventArgs e) public void ParentResize()
{ {
base.OnResize(e); ForceUpdate();
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);
} }
private int frame = 0; private int frame = 0;
@ -249,7 +245,11 @@ public class FPSWindow : GameWindow , IWindow
protected override void OnResize(ResizeEventArgs e) 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) protected override void OnClosing(CancelEventArgs e)
@ -400,7 +400,7 @@ public class FPSWindow : GameWindow , IWindow
{ {
if (!Controls[i].Loaded) continue; if (!Controls[i].Loaded) continue;
GL.Scissor(0, 0, Size.X, Size.Y); 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(); Context.SwapBuffers();
base.OnRenderFrame(args); base.OnRenderFrame(args);

View File

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

View File

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

View File

@ -1,5 +1,6 @@
using GraphicsManager.Enums; using GraphicsManager.Enums;
using GraphicsManager.Objects; using GraphicsManager.Objects;
using GraphicsManager.Objects.Core;
using OpenTK.Mathematics; using OpenTK.Mathematics;
using OpenTK.Windowing.Common; using OpenTK.Windowing.Common;
using OpenTK.Windowing.Common.Input; using OpenTK.Windowing.Common.Input;
@ -17,13 +18,19 @@ public interface IRenderObject
public bool AllowHoverFromBehind { get; set; } public bool AllowHoverFromBehind { get; set; }
public bool Loaded { get; } public bool Loaded { get; }
public void LoadToParent(IParent Parent, IWindow Window); 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 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 Clean();
public void Focus(); public void Focus();
public void UnFocus(); public void UnFocus();
public void SendKeyEvent(KeyboardKeyEventArgs KeyArgs); public void SendKeyEvent(KeyboardKeyEventArgs KeyArgs);
public void SendClipEvent(string Text); public void SendClipEvent(string Text);
public void SendFilesEvent(string[] Files);
public Vector2i Size { get; set; } public Vector2i Size { get; set; }
public Vector3i Location { get; set; } public Vector3i Location { get; set; }
public Vector2 SizeAsFloat { get; } public Vector2 SizeAsFloat { get; }
@ -33,9 +40,11 @@ public interface IRenderObject
public IWindow? Window { get; } public IWindow? Window { get; }
public bool Visible { get; set; } public bool Visible { get; set; }
public object? Tag { get; set; } public object? Tag { get; set; }
public List<SubHitBox> SubHitBoxes { get; }
public event Func<IRenderObject, Task>? Clicked; public event Func<IRenderObject, Task>? Clicked;
public event Func<IRenderObject, Task>? MouseLeave; public event Func<IRenderObject, Task>? MouseLeave;
public event Func<IRenderObject, string[], Task>? FilesDroped;
public event Func<IRenderObject, Task>? MouseEnter; public event Func<IRenderObject, Task>? MouseEnter;
public event Func<IRenderObject, Task>? SizeChanged; public event Func<IRenderObject, Task>? SizeChanged;
public event Func<IRenderObject, Task>? WindowLoaded; public event Func<IRenderObject, Task>? WindowLoaded;

View File

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

View File

@ -39,4 +39,12 @@ public class Font
fontclass.Face = new Face(lib, Font.ToArray(), 0); fontclass.Face = new Face(lib, Font.ToArray(), 0);
return fontclass; 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; private static uint index = 0;
public event Func<Task>? ReloadUI; public event Func<Task>? ReloadUI;
public static bool MemoryFont;
public static string FontPath = Path.GetTempPath();
public required string Family { get; init; } public required string Family { get; init; }
private FontSize fs = FontSize.Thin; private FontSize fs = FontSize.Thin;
internal Dictionary<FontSize, Tuple<string, Font?>> InternalFonts = new(); //internal Dictionary<FontSize, Font> InternalFonts = new();
internal Dictionary<FontSize, Tuple<string, Font?>> InternalFontsi = new(); //internal Dictionary<FontSize, Font> InternalFontsi = new();
internal bool IsZip = false; //internal bool IsZip = false;
internal Dictionary<FontSize, Tuple<MemoryStream, Font?>> SInternalFonts = new(); internal Dictionary<FontSize, Font> InternalFonts = new();
internal Dictionary<FontSize, Tuple<MemoryStream, Font?>> SInternalFontsi = new(); internal Dictionary<FontSize, Font> InternalFontsi = new();
internal static List<FontFamily> AllFams = new(); internal static List<FontFamily> AllFams = new();
public static Task<FontFamily> LoadFontFamilyTask(Stream FamilyZip, string Family, string extra = "-") public static Task<FontFamily> LoadFontFamilyTask(Stream FamilyZip, string Family, string extra = "-")
@ -25,14 +27,13 @@ public class FontFamily
public static FontFamily LoadFontFamily(Stream FamilyZip, string Family, string extra = "-") public static FontFamily LoadFontFamily(Stream FamilyZip, string Family, string extra = "-")
{ {
extra = extra.ToLower(); extra = extra.ToLower();
FontFamily f = new() FontFamily f = new()
{ {
Family = Family Family = Family
}; };
AllFams.Add(f); AllFams.Add(f);
using ZipArchive archive = new ZipArchive(FamilyZip, ZipArchiveMode.Read, false); using ZipArchive archive = new ZipArchive(FamilyZip, ZipArchiveMode.Read, false);
f.IsZip = true;
foreach (ZipArchiveEntry font in archive.Entries) foreach (ZipArchiveEntry font in archive.Entries)
{ {
@ -42,20 +43,57 @@ public class FontFamily
void tryadd(FontSize s, bool i = false) void tryadd(FontSize s, bool i = false)
{ {
var memoryStream = new MemoryStream(); if (MemoryFont)
var ss = font.Open();
ss.CopyTo(memoryStream);
if (i)
{ {
if (!f.SInternalFontsi.ContainsKey(s)) using (var ss = font.Open())
f.SInternalFontsi.Add(s, new(memoryStream, null)); {
using (var memoryStream = new MemoryStream())
{
ss.CopyTo(memoryStream);
byte[] fontBytes = memoryStream.ToArray();
if (i)
{
if (!f.InternalFontsi.ContainsKey(s))
{
f.InternalFontsi.Add(s, Font.MakeFontFromByteArray(fontBytes));
}
}
else
{
if (!f.InternalFonts.ContainsKey(s))
{
f.InternalFonts.Add(s, Font.MakeFontFromByteArray(fontBytes));
}
}
}
}
} }
else else
{ {
if (!f.SInternalFonts.ContainsKey(s)) string p = FontPath;
f.SInternalFonts.Add(s, new(memoryStream, null)); 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")) if (fd.EndsWith("italic"))
@ -84,7 +122,7 @@ public class FontFamily
} }
} }
FamilyZip.Dispose(); FamilyZip.Dispose();
return f; return f;
} }

View File

@ -73,108 +73,22 @@ public class FontInteraction
CurrentFonts = new Font[Families_.Count]; CurrentFonts = new Font[Families_.Count];
for (int j = 0; j < Families_.Count; j++) for (int j = 0; j < Families_.Count; j++)
{ {
if (Families_[j].IsZip) if (value)
{ {
if (value) if (Families_[j].InternalFontsi.TryGetValue(FontSize, out Font? f))
{ {
if (Families_[j].SInternalFontsi.TryGetValue(FontSize, out Tuple<MemoryStream, Font?>? f)) i = value;
{ CurrentFonts[j] = (Families_[j].InternalFontsi[fs]);
i = value; if (ReloadUI is not null) ReloadUI.Invoke();
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!);
if (ReloadUI is not null) ReloadUI.Invoke();
}
}
else
{
if (Families_[j].SInternalFonts.TryGetValue(FontSize, out Tuple<MemoryStream, 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!;
if (ReloadUI is not null) ReloadUI.Invoke();
}
} }
} }
else else
{ {
if (value) if (Families_[j].InternalFonts.TryGetValue(FontSize, out Font? f))
{ {
if (Families_[j].InternalFontsi.TryGetValue(FontSize, out Tuple<string, Font?>? f)) i = value;
{ CurrentFonts[j] = Families_[j].InternalFonts[fs];
i = value; if (ReloadUI is not null) ReloadUI.Invoke();
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) 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; Dictionary<FontSize, Tuple<string, Font?>>.KeyCollection keys = thisList.Keys;
FontSize nearest = thisValue - FontSize nearest = keys.OrderBy(k => Math.Abs(k - thisValue)).First();
keys.Where(k => k <= thisValue)
.Min(k => thisValue - k);
fs = nearest; fs = nearest;
return thisList[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) 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; Dictionary<FontSize, Tuple<MemoryStream, Font?>>.KeyCollection keys = thisList.Keys;
FontSize nearest = thisValue - FontSize nearest = keys.OrderBy(k => Math.Abs(k - thisValue)).First();
keys.Where(k => k <= thisValue) fs = nearest;
.Min(k => thisValue - k); 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; fs = nearest;
return thisList[nearest]; return thisList[nearest];
} }
@ -210,61 +128,17 @@ public class FontInteraction
CurrentFonts = new Font[Families_.Count]; CurrentFonts = new Font[Families_.Count];
for (int j = 0; j < Families_.Count; j++) 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].InternalFontsi, value, out fs),
{ false => Sgcl(Families_[j].InternalFonts, value, out fs),
true => Sgcl(Families_[j].SInternalFontsi, value, out fs), };
false => Sgcl(Families_[j].SInternalFonts, 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 CurrentFonts[j] = Italic switch
{
true => Families_[j].SInternalFontsi[fs].Item2!,
false => Families_[j].SInternalFonts[fs].Item2!,
};
}
else
{ {
Tuple<string, Font?> f = Italic switch true => Families_[j].InternalFontsi[fs],
{ false => Families_[j].InternalFonts[fs],
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(); 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(); if (!BlockDraw && Parent is not null) Parent.TryDraw();
} }
public virtual void ParentResize(ResizeEventArgs e) public virtual void ParentResize()
{ {
bool PastBlockState = BlockDraw;
BlockDraw = true; BlockDraw = true;
if (e.Width == 0 && e.Height == 0) return;
for (int i = 0; i < Controls.Length; i++) for (int i = 0; i < Controls.Length; i++)
{ {
if (!Controls[i].Loaded) continue; 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 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 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); int sx = (right ? Size.X - Controls[i].Distance.X - lx : Controls[i].Size.X);
Controls[i].Size = new(sx, sy); bool mooved = false;
Controls[i].Location = new(lx, ly, Controls[i].Location.Z); if (sx != Controls[i].Size.X || sy != Controls[i].Size.Y)
if (Controls[i] is IParent parent)
{ {
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(); if (Parent is not null) Parent.TryDraw();
BlockDraw = PastBlockState; BlockDraw = false;
} }
public virtual void ReportSizeUpdate(IRenderObject Control) 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) 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 - sx + x > sw || Location.Y - sy + y > sh)
if (Location.X > nw)
return; return;
else
{
nx += Location.X;
nw -= Location.X;
if (Size.X < nw)
nw = Size.X;
}
if (Location.Y > nh) if (Location.X - sx + x > -1)
return; {
else int add = Location.X - sx + x;
{ sx += add;
if (Location.Y > -1) sw -= add;
{ if (Size.X < sw)
ny += Location.Y; sw = Size.X;
nh -= Location.Y; }
if (Size.Y < nh) else
nh = Size.Y; {
} if (Size.X + Location.X - sx + x < sw)
else sw = Size.X + Location.X - sx + x;
{ }
if (Size.Y + Location.Y < nh) if (Location.Y - sy + y > -1)
nh = Size.Y + Location.Y; {
} int add = Location.Y - sy + y;
} sy += add;
if (nw == 0 || nh == 0) return; sh -= add;
GL.Scissor(nx, Window!.CS.Y - ny - nh, nw, nh); if (Size.Y < sh)
base.Draw(nx,ny,nw,nh); sh = Size.Y;
}
else
{
if (Size.Y + Location.Y - sy + y < sh)
sh = Size.Y + Location.Y - sy + y;
}
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); IEnumerable<IRenderObject> needload = Controls.Where(a => a.Loaded == false);
if (needload.Any()) if (needload.Any())
@ -108,8 +119,8 @@ public abstract class ParentBase : Rectangle, IParent
for (int i = 0; i < Controls.Length; i++) for (int i = 0; i < Controls.Length; i++)
{ {
if (Controls[i].Location.X > Size.X || Controls[i].Location.Y > Size.Y) continue; if (Controls[i].Location.X > Size.X || Controls[i].Location.Y > Size.Y) continue;
GL.Scissor(nx, Window!.CS.Y - ny - nh, nw, nh); GL.Scissor(sx, Window!.CS.Y - sy - sh, sw, sh);
Controls[i].Draw(nx, ny, nw, nh); 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; Controls[i].Location = Controls[i].Location;
} }
ParentResize(new()); ParentResize();
if (Parent is not null) Parent.TryDraw(); if (Parent is not null) Parent.TryDraw();
BlockDraw = false; BlockDraw = false;
} }

View File

@ -60,11 +60,11 @@ public class RoundedButton : Rectangle
base.Clean(); 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; if (!Visible || !Loaded) return;
base.Draw(x,y,w,h); base.Draw(x,y,sx,sy,sw,sh);
_label.Draw(x,y,w,h); _label.Draw(x,y,sx,sy,sw,sh);
} }
public override void LoadToParent(IParent Parent, IWindow Window) 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); 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) public void SetMatrixF4(string name, Matrix4 data)
{ {
GL.UseProgram(Handle); 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); ushort temp = (charter);
if (face.GetCharIndex(temp) == 0) 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 try
{ {
@ -203,7 +203,7 @@ public class Texture
return GetChar(l.CurrentFonts[0].Face, (char)1); 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 try
{ {
@ -235,7 +235,7 @@ public class Texture
private static Dictionary<FontInteraction, Texture> BadChars = new(); 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 try
{ {

View File

@ -200,20 +200,25 @@ public class FlowLayout : ParentBase, IFlow
return Task.CompletedTask; 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 public override Vector2i Size
{ {
get => base.Size; get => base.Size;
set set
{ {
BlockDraw = true; SetSize(value.X, value.Y);
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;
} }
} }

View File

@ -1,4 +1,5 @@
using GraphicsManager.Enums; using System.Text;
using GraphicsManager.Enums;
using GraphicsManager.Interfaces; using GraphicsManager.Interfaces;
using GraphicsManager.Objects.Core; using GraphicsManager.Objects.Core;
using GraphicsManager.Structs; using GraphicsManager.Structs;
@ -11,353 +12,27 @@ using OpenTK.Windowing.GraphicsLibraryFramework;
namespace GraphicsManager.Objects; namespace GraphicsManager.Objects;
public class Label : ILabel public class Label : LabelBase
{ {
public static readonly Dictionary<IGLFWGraphicsContext, Shader> DefaultTextShader = new(); public static readonly Dictionary<IGLFWGraphicsContext, Shader> DefaultTextShader = new();
public Label(FontFamily fontFamily) public Label(FontFamily fontFamily):base(fontFamily)
{ {
Font = FontInteraction.Load(fontFamily); Font = FontInteraction.Load(fontFamily);
} }
public Label(FontInteraction interaction) public Label(FontInteraction interaction):base(interaction)
{ {
Font = 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 Color4 Color { get; set; } = new Color4(255, 255, 255, 255);
public Vector2i Distance { get; set; } public override void Draw(int x, int y, int sx, int sy, int sw, int sh)
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)
{ {
if (Visible && Loaded && this.Font is not null) if (Visible && Loaded && this.Font is not null)
{ {
if (!Window!.Context.IsCurrent) Window.Context.MakeCurrent(); if (!Window!.Context.IsCurrent) Window.Context.MakeCurrent();
Shader.Use(); Shader.Use();
GL.Enable(EnableCap.Blend);
GL.Uniform4(Shader.GetUniformLocation("textColor"), Color); GL.Uniform4(Shader.GetUniformLocation("textColor"), Color);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.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(); if (UpdateOnDraw) UpdateProgress();
base.Draw(x, y, w, h); base.Draw(x, y, sx,sy, sw, sh);
} }
public void UpdateProgress() 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 GraphicsManager.Objects.Core;
using OpenTK.Graphics.OpenGL4; using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics; using OpenTK.Mathematics;
using OpenTK.Platform.Windows;
using OpenTK.Windowing.Common; using OpenTK.Windowing.Common;
using OpenTK.Windowing.Common.Input; using OpenTK.Windowing.Common.Input;
using OpenTK.Windowing.Desktop; using OpenTK.Windowing.Desktop;
@ -50,7 +51,6 @@ public class Rectangle : ITextureObject
public List<Texture> Textures { get; set; } = new(); public List<Texture> Textures { get; set; } = new();
public BetterContextMenu? ContextMenu { get; set; } = null; public BetterContextMenu? ContextMenu { get; set; } = null;
public event Func<string[], Task>? FilesDroped;
public Rectangle(Texture? texture) public Rectangle(Texture? texture)
{ {
@ -92,7 +92,6 @@ public class Rectangle : ITextureObject
} }
} }
public Action? OnDrawAction;
public virtual void SendKeyEvent(KeyboardKeyEventArgs KeyArgs) 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 (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(); if (!Window!.Context.IsCurrent) Window.Context.MakeCurrent();
foreach (Texture tex in Textures) foreach (Texture tex in Textures)
{ {
tex.Use(); tex.Use();
} }
Shader.Use(); Shader.Use();
Shader.SetMatrix4("windowMatrix", Window.WindowSizeMatrix); Shader.SetMatrix4(Shader.GetUniformLocation("windowMatrix"), Window.WindowSizeMatrix);
if (!Textures.Any() || Shader.Handle == DefaultAlphaShader[Window!.Context].Handle) if (!Textures.Any() || Shader.Handle == DefaultAlphaShader[Window!.Context].Handle)
{ {
GL.Uniform4(0, BackgroundColor); GL.Uniform4(Shader.GetUniformLocation("objColor"), BackgroundColor);
} }
GL.BindVertexArray(ArrayObject); GL.BindVertexArray(ArrayObject);
GL.DrawElements(PrimitiveType.Triangles, Indexs.Length, DrawElementsType.UnsignedShort, 0); 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 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() public void ForceDistanceUpdate()
{ {
@ -135,7 +138,8 @@ public class Rectangle : ITextureObject
public void ForceDistanceUpdate(IParent parent) 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() public virtual void Clean()
@ -168,8 +172,8 @@ public class Rectangle : ITextureObject
Loaded = true; Loaded = true;
Window.MouseDown += Window_MouseDown; Window.MouseDown += Window_MouseDown;
Window.FileDrop += WindowOnFileDrop; Window.FileDrop += WindowOnFileDrop;
Location = Location; SetLocation(loc_.X, loc_.Y, loc_.Z);
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) ForceDistanceUpdate(Parent);
if (WindowLoaded is not null) WindowLoaded.Invoke(this); if (WindowLoaded is not null) WindowLoaded.Invoke(this);
} }
@ -187,7 +191,7 @@ public class Rectangle : ITextureObject
private void WindowOnFileDrop(FileDropEventArgs obj) private void WindowOnFileDrop(FileDropEventArgs obj)
{ {
if (!MouseInside) return; 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; private bool mi = false;
@ -456,201 +460,179 @@ public class Rectangle : ITextureObject
} }
set set
{ {
size_ = value; SetSize(value.X, value.Y);
if (Window is null || Parent is null) return; }
Parent.ReportSizeUpdate(this); }
//float[] temp = Points;
float[] temp = Textures.Count == 0
? new float[12]
: TextureDisplay switch
{
TextureDisplay.Clamped => new float[20],
TextureDisplay.HorizontalCenter or TextureDisplay.ProgressHorizontalCenter or TextureDisplay.TextureHorizontalCenter => new float[40],
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));
temp[2] = Location.Z;
temp[(!Textures.Any() ? 5 : 7)] = Location.Z;
temp[(!Textures.Any() ? 8 : 12)] = Location.Z;
temp[(!Textures.Any() ? 11 : 17)] = Location.Z;
temp[0] = saf.X; // top r public virtual void SetSize(int wh)
temp[1] = laf.Y; {
temp[(!Textures.Any()? 3 : 5)] = saf.X; // bot r SetSize(wh, wh);
temp[(!Textures.Any() ? 4 : 6)] = saf.Y; }
temp[(!Textures.Any() ? 6 : 10)] = laf.X;//bot l public virtual void SetSize(int w, int h)
temp[(!Textures.Any() ? 7 : 11)] = saf.Y; {
temp[(!Textures.Any() ? 9 : 15)] = laf.X;//top l size_.X = w;
temp[(!Textures.Any() ? 10 : 16)] = laf.Y; size_.Y = h;
if (Window is null || Parent is null) return;
if (Textures.Count > 0) Parent.ReportSizeUpdate(this);
float[] temp = Textures.Count == 0
? new float[12]
: TextureDisplay switch
{ {
Vector2i s = value; TextureDisplay.Clamped => new float[20],
float diff = Window.IntToWindow(s.Y) + 1; TextureDisplay.HorizontalCenter or TextureDisplay.ProgressHorizontalCenter or TextureDisplay.TextureHorizontalCenter => new float[40],
float per = (float)Textures[0].RawSize!.Value.Y / Textures[0].RawSize!.Value.X; TextureDisplay.Center => new float[80],
if (TextureDisplay == TextureDisplay.TextureHorizontalCenter) _ => new float[20]
diff = Window.IntToWindow(Textures[0].RawSize!.Value.Y); };
if (TextureDisplay == TextureDisplay.Center) saf.X = Parent.IntToWindow(w + loc_.X);
{ saf.Y = Parent.IntToWindow(h + loc_.Y, true);
if (s.X > Textures[0].RawSize!.Value.X) temp[2] = Location.Z;
diff = (Window.IntToWindow(Textures[0].RawSize!.Value.X) + 1) / 3; temp[(!Textures.Any() ? 5 : 7)] = Location.Z;
temp[(!Textures.Any() ? 8 : 12)] = Location.Z;
temp[(!Textures.Any() ? 11 : 17)] = Location.Z;
temp[0] = saf.X; // top r
temp[1] = laf.Y;
temp[(!Textures.Any()? 3 : 5)] = saf.X; // bot r
temp[(!Textures.Any() ? 4 : 6)] = saf.Y;
temp[(!Textures.Any() ? 6 : 10)] = laf.X;//bot l
temp[(!Textures.Any() ? 7 : 11)] = saf.Y;
temp[(!Textures.Any() ? 9 : 15)] = laf.X;//top l
temp[(!Textures.Any() ? 10 : 16)] = laf.Y;
if (Textures.Count > 0)
{
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 (w> Textures[0].RawSize!.Value.X)
diff = (Window.IntToWindow(Textures[0].RawSize!.Value.X) + 1) / 3;
else
diff = (Window.IntToWindow(w) + 1) / 3;
per = Textures[0].MaxText.X / 3;
}
switch (TextureDisplay)
{
case TextureDisplay.Clamped:
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X;
temp[19] = Textures[0].MaxText.Y;
break;
case TextureDisplay.HorizontalCenter:
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X;
temp[19] = Textures[0].MaxText.Y;
temp[20] = saf.X - diff; // top r
temp[21] = laf.Y;
temp[22] = 0;
temp[23] = Textures[0].MaxText.X - per;
temp[24] = 1;
temp[25] = saf.X - diff; // bot r
temp[26] = saf.Y;
temp[27] = 0;
temp[28] = Textures[0].MaxText.X - per;
temp[29] = 0;
temp[30] = laf.X + diff; // bot l
temp[31] = saf.Y;
temp[32] = 0;
temp[33] = per;
temp[34] = 0;
temp[35] = laf.X + diff; // top l
temp[36] = laf.Y;
temp[37] = 0;
temp[38] = per;
temp[39] = 1;
break;
case TextureDisplay.Center:
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X;
temp[19] = Textures[0].MaxText.Y;
int dy, dx;
if (h > Textures[0].RawSize!.Value.Y)
dy = Textures[0].RawSize!.Value.Y;
else else
diff = (Window.IntToWindow(s.X) + 1) / 3; dy = h;
if (w > Textures[0].RawSize!.Value.X)
dx = Textures[0].RawSize!.Value.X;
else
dx = w;
if (dy > dx) dy = dx;
else dx = dy;
float diffy = (dy + 1) / (float)3;
diff = (dx + 1) / (float)3;
per = Textures[0].MaxText.X / 3; per = Textures[0].MaxText.X / 3;
}
switch (TextureDisplay) SetPoint(temp, 20, temp[0], temp[1] + diffy, temp[2], temp[3], temp[4] - (temp[4]*per));
{ SetPoint(temp, 25, temp[0], temp[6] - diffy, temp[2], temp[3], temp[4] * per);
case TextureDisplay.Clamped: SetPoint(temp, 30, temp[5] - diff, temp[6], temp[2], temp[3] - (temp[3]*per), temp[9]);
temp[3] = Textures[0].MaxText.X; SetPoint(temp, 35, temp[10] + diff, temp[6], temp[2], temp[3] * per, temp[9]);
temp[4] = Textures[0].MaxText.Y; SetPoint(temp, 40, temp[10], temp[26], temp[2], temp[13], temp[29]);
temp[8] = Textures[0].MaxText.X; SetPoint(temp, 45, temp[10], temp[21], temp[2], temp[13], temp[24]);
temp[19] = Textures[0].MaxText.Y; SetPoint(temp, 50, temp[35], temp[1], temp[2], temp[38], temp[4]);
break; SetPoint(temp, 55, temp[30], temp[1], temp[2], temp[33], temp[4]);
case TextureDisplay.HorizontalCenter: SetPoint(temp, 60, temp[30], temp[21], temp[2], temp[33], temp[24]);
temp[3] = Textures[0].MaxText.X; SetPoint(temp, 65, temp[30], temp[26], temp[2], temp[33], temp[29]);
temp[4] = Textures[0].MaxText.Y; SetPoint(temp, 70, temp[35], temp[26], temp[2], temp[38], temp[29]);
temp[8] = Textures[0].MaxText.X; SetPoint(temp, 75, temp[35], temp[21], temp[2], temp[38], temp[24]);
temp[19] = Textures[0].MaxText.Y; break;
temp[20] = saf.X - diff; // top r case TextureDisplay.ProgressHorizontalCenter:
temp[21] = laf.Y; if (w > h)
temp[22] = 0; {
temp[23] = Textures[0].MaxText.X - per; if (w > h+ h)
temp[24] = 1;
temp[25] = saf.X - diff; // bot r
temp[26] = saf.Y;
temp[27] = 0;
temp[28] = Textures[0].MaxText.X - per;
temp[29] = 0;
temp[30] = laf.X + diff; // bot l
temp[31] = saf.Y;
temp[32] = 0;
temp[33] = per;
temp[34] = 0;
temp[35] = laf.X + diff; // top l
temp[36] = laf.Y;
temp[37] = 0;
temp[38] = per;
temp[39] = 1;
break;
case TextureDisplay.Center:
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X;
temp[19] = Textures[0].MaxText.Y;
int dy, dx;
if (s.Y > Textures[0].RawSize!.Value.Y)
dy = Textures[0].RawSize!.Value.Y;
else
dy = s.Y;
if (s.X > Textures[0].RawSize!.Value.X)
dx = Textures[0].RawSize!.Value.X;
else
dx = s.X;
if (dy > dx) dy = dx;
else dx = dy;
float diffy = (dy + 1) / (float)3;
diff = (dx + 1) / (float)3;
per = Textures[0].MaxText.X / 3;
SetPoint(temp, 20, temp[0], temp[1] + diffy, temp[2], temp[3], temp[4] - (temp[4]*per));
SetPoint(temp, 25, temp[0], temp[6] - diffy, temp[2], temp[3], temp[4] * per);
SetPoint(temp, 30, temp[5] - diff, temp[6], temp[2], temp[3] - (temp[3]*per), temp[9]);
SetPoint(temp, 35, temp[10] + diff, temp[6], temp[2], temp[3] * per, temp[9]);
SetPoint(temp, 40, temp[10], temp[26], temp[2], temp[13], temp[29]);
SetPoint(temp, 45, temp[10], temp[21], temp[2], temp[13], temp[24]);
SetPoint(temp, 50, temp[35], temp[1], temp[2], temp[38], temp[4]);
SetPoint(temp, 55, temp[30], temp[1], temp[2], temp[33], temp[4]);
SetPoint(temp, 60, temp[30], temp[21], temp[2], temp[33], temp[24]);
SetPoint(temp, 65, temp[30], temp[26], temp[2], temp[33], temp[29]);
SetPoint(temp, 70, temp[35], temp[26], temp[2], temp[38], temp[29]);
SetPoint(temp, 75, temp[35], temp[21], temp[2], temp[38], temp[24]);
break;
case TextureDisplay.ProgressHorizontalCenter:
if (s.X > s.Y)
{ {
if (s.X > s.Y + s.Y) temp[3] = Textures[0].MaxText.X;
{ temp[4] = Textures[0].MaxText.Y;
temp[3] = Textures[0].MaxText.X; temp[8] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y; temp[19] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X; temp[20] = saf.X - diff; // top r
temp[19] = Textures[0].MaxText.Y; temp[21] = laf.Y;
temp[20] = saf.X - diff; // top r temp[22] = 0;
temp[21] = laf.Y; temp[23] = Textures[0].MaxText.X - per;
temp[22] = 0; temp[24] = 1;
temp[23] = Textures[0].MaxText.X - per;
temp[24] = 1;
temp[25] = saf.X - diff; // bot r temp[25] = saf.X - diff; // bot r
temp[26] = saf.Y; temp[26] = saf.Y;
temp[27] = 0; temp[27] = 0;
temp[28] = 1 - per; temp[28] = 1 - per;
temp[29] = 0; temp[29] = 0;
temp[30] = laf.X + diff; // bot l temp[30] = laf.X + diff; // bot l
temp[31] = saf.Y; temp[31] = saf.Y;
temp[32] = 0; temp[32] = 0;
temp[33] = per; temp[33] = per;
temp[34] = 0; temp[34] = 0;
temp[35] = laf.X + diff; // top l temp[35] = laf.X + diff; // top l
temp[36] = laf.Y; temp[36] = laf.Y;
temp[37] = 0; temp[37] = 0;
temp[38] = per; temp[38] = per;
temp[39] = 1; temp[39] = 1;
}
else
{
temp[3] = (0.666666f + (((s.X - s.Y) / (float)s.Y)* per)) * Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = temp[3];
temp[19] = Textures[0].MaxText.Y;
//start last 33% of texture
temp[20] = saf.X; // top r
temp[21] = laf.Y;
temp[22] = 0;
temp[23] = temp[3];
temp[24] = 1;
temp[25] = saf.X; // bot r
temp[26] = saf.Y;
temp[27] = 0;
temp[28] = temp[3];
temp[29] = 0;
temp[30] = laf.X + diff; // bot l
temp[31] = saf.Y;
temp[32] = 0;
temp[33] = per;
temp[34] = 0;
temp[35] = laf.X + diff; // top l
temp[36] = laf.Y;
temp[37] = 0;
temp[38] = per;
temp[39] = 1;
}
} }
else else
{ {
//first 33% of texture temp[3] = (0.666666f + (((w - h) / (float)h)* per)) * Textures[0].MaxText.X;
temp[3] = ((s.X/(float)s.Y)*per);
temp[4] = Textures[0].MaxText.Y; temp[4] = Textures[0].MaxText.Y;
temp[8] = temp[3]; temp[8] = temp[3];
temp[19] = Textures[0].MaxText.Y; temp[19] = Textures[0].MaxText.Y;
//start last 33% of texture
temp[20] = saf.X; // top r temp[20] = saf.X; // top r
temp[21] = laf.Y; temp[21] = laf.Y;
temp[22] = 0; temp[22] = 0;
temp[23] = temp[3]; temp[23] = temp[3];
temp[24] = Textures[0].MaxText.Y; temp[24] = 1;
temp[25] = saf.X; // bot r temp[25] = saf.X; // bot r
temp[26] = saf.Y; temp[26] = saf.Y;
@ -658,25 +640,285 @@ public class Rectangle : ITextureObject
temp[28] = temp[3]; temp[28] = temp[3];
temp[29] = 0; temp[29] = 0;
temp[30] = saf.X; // bot l temp[30] = laf.X + diff; // bot l
temp[31] = saf.Y; temp[31] = saf.Y;
temp[32] = 0; temp[32] = 0;
temp[33] = temp[3]; temp[33] = per;
temp[34] = 0; temp[34] = 0;
temp[35] = saf.X; // top l temp[35] = laf.X + diff; // top l
temp[36] = laf.Y; temp[36] = laf.Y;
temp[37] = 0; temp[37] = 0;
temp[38] = temp[3]; temp[38] = per;
temp[39] = Textures[0].MaxText.Y; temp[39] = 1;
} }
break; }
} else
} {
//first 33% of texture
temp[3] = ((w/(float)h)*per);
temp[4] = Textures[0].MaxText.Y;
temp[8] = temp[3];
temp[19] = Textures[0].MaxText.Y;
temp[20] = saf.X; // top r
temp[21] = laf.Y;
temp[22] = 0;
temp[23] = temp[3];
temp[24] = Textures[0].MaxText.Y;
Points = temp; temp[25] = saf.X; // bot r
if (SizeChanged is not null) SizeChanged.Invoke(this); temp[26] = saf.Y;
temp[27] = 0;
temp[28] = temp[3];
temp[29] = 0;
temp[30] = saf.X; // bot l
temp[31] = saf.Y;
temp[32] = 0;
temp[33] = temp[3];
temp[34] = 0;
temp[35] = saf.X; // top l
temp[36] = laf.Y;
temp[37] = 0;
temp[38] = temp[3];
temp[39] = Textures[0].MaxText.Y;
}
break;
}
} }
Points = temp;
temp = Array.Empty<float>();
if (SizeChanged is not null) SizeChanged.Invoke(this);
}
public virtual void SetLocation(int x, int y)
{
SetLocation(x, y, Location.Z);
}
public virtual void SetLocation(int xy)
{
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]
: TextureDisplay switch
{
TextureDisplay.Clamped => new float[20],
TextureDisplay.HorizontalCenter or TextureDisplay.ProgressHorizontalCenter => new float[40],
TextureDisplay.Center => new float[80],
_ => new float[20]
};
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.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;
temp[(!Textures.Any() ? 7 : 11)] = saf.Y;
if (Textures.Count > 0)
{
Vector2i s = Size;
float diff = Window.IntToWindow(s.Y) + 1;
float per = (float)Textures[0].RawSize!.Value.Y / Textures[0].RawSize!.Value.X;
if (TextureDisplay == TextureDisplay.Center)
{
if (s.X > Textures[0].RawSize!.Value.X)
diff = (Window.IntToWindow(Textures[0].RawSize!.Value.X) + 1) / 3;
else
diff = (Window.IntToWindow(s.X) + 1) / 3;
per = Textures[0].MaxText.X / 3;
}
switch (TextureDisplay)
{
case TextureDisplay.Clamped:
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X;
temp[19] = Textures[0].MaxText.Y;
break;
case TextureDisplay.HorizontalCenter:
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X;
temp[19] = Textures[0].MaxText.Y;
temp[20] = saf.X - diff; // top r
temp[21] = laf.Y;
temp[22] = 0;
temp[23] = Textures[0].MaxText.X - per;
temp[24] = 1;
temp[25] = saf.X - diff; // bot r
temp[26] = saf.Y;
temp[27] = 0;
temp[28] = Textures[0].MaxText.X - per;
temp[29] = 0;
temp[30] = laf.X + diff; // bot l
temp[31] = saf.Y;
temp[32] = 0;
temp[33] = per;
temp[34] = 0;
temp[35] = laf.X + diff; // top l
temp[36] = laf.Y;
temp[37] = 0;
temp[38] = per;
temp[39] = 1;
break;
case TextureDisplay.Center:
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X;
temp[19] = Textures[0].MaxText.Y;
int dy, dx;
if (s.Y > Textures[0].RawSize!.Value.Y)
dy = Textures[0].RawSize!.Value.Y;
else
dy = s.Y;
if (s.X > Textures[0].RawSize!.Value.X)
dx = Textures[0].RawSize!.Value.X;
else
dx = s.X;
if (dy > dx) dy = dx;
else dx = dy;
float diffy = (dy + 1) / (float)3;
diff = (dx + 1) / (float)3;
SetPoint(temp, 20, temp[0], temp[1] + diffy, temp[2], temp[3], temp[4] - (temp[4]*per));
SetPoint(temp, 25, temp[0], temp[6] - diffy, temp[2], temp[3], temp[4] * per);
SetPoint(temp, 30, temp[5] - diff, temp[6], temp[2], temp[3] - (temp[3]*per), temp[9]);
SetPoint(temp, 35, temp[10] + diff, temp[6], temp[2], temp[3] * per, temp[9]);
SetPoint(temp, 40, temp[10], temp[26], temp[2], temp[13], temp[29]);
SetPoint(temp, 45, temp[10], temp[21], temp[2], temp[13], temp[24]);
SetPoint(temp, 50, temp[35], temp[1], temp[2], temp[38], temp[4]);
SetPoint(temp, 55, temp[30], temp[1], temp[2], temp[33], temp[4]);
SetPoint(temp, 60, temp[30], temp[21], temp[2], temp[33], temp[24]);
SetPoint(temp, 65, temp[30], temp[26], temp[2], temp[33], temp[29]);
SetPoint(temp, 70, temp[35], temp[26], temp[2], temp[38], temp[29]);
SetPoint(temp, 75, temp[35], temp[21], temp[2], temp[38], temp[24]);
break;
case TextureDisplay.ProgressHorizontalCenter:
if (s.X > s.Y)
{
if (s.X > s.Y + s.Y)
{
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X;
temp[19] = Textures[0].MaxText.Y;
temp[20] = saf.X - diff; // top r
temp[21] = laf.Y;
temp[22] = 0;
temp[23] = Textures[0].MaxText.X - per;
temp[24] = 1;
temp[25] = saf.X - diff; // bot r
temp[26] = saf.Y;
temp[27] = 0;
temp[28] = 1 - per;
temp[29] = 0;
temp[30] = laf.X + diff; // bot l
temp[31] = saf.Y;
temp[32] = 0;
temp[33] = per;
temp[34] = 0;
temp[35] = laf.X + diff; // top l
temp[36] = laf.Y;
temp[37] = 0;
temp[38] = per;
temp[39] = 1;
}
else
{
temp[3] = (0.666666f + (((s.X - s.Y) / (float)s.Y)* per)) * Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = temp[3];
temp[19] = Textures[0].MaxText.Y;
//start last 33% of texture
temp[20] = saf.X; // top r
temp[21] = laf.Y;
temp[22] = 0;
temp[23] = temp[3];
temp[24] = 1;
temp[25] = saf.X; // bot r
temp[26] = saf.Y;
temp[27] = 0;
temp[28] = temp[3];
temp[29] = 0;
temp[30] = laf.X + diff; // bot l
temp[31] = saf.Y;
temp[32] = 0;
temp[33] = per;
temp[34] = 0;
temp[35] = laf.X + diff; // top l
temp[36] = laf.Y;
temp[37] = 0;
temp[38] = per;
temp[39] = 1;
}
}
else
{
//first 33% of texture
temp[3] = ((s.X/(float)s.Y)*per);
temp[4] = Textures[0].MaxText.Y;
temp[8] = temp[3];
temp[19] = Textures[0].MaxText.Y;
temp[20] = saf.X; // top r
temp[21] = laf.Y;
temp[22] = 0;
temp[23] = temp[3];
temp[24] = Textures[0].MaxText.Y;
temp[25] = saf.X; // bot r
temp[26] = saf.Y;
temp[27] = 0;
temp[28] = temp[3];
temp[29] = 0;
temp[30] = saf.X; // bot l
temp[31] = saf.Y;
temp[32] = 0;
temp[33] = temp[3];
temp[34] = 0;
temp[35] = saf.X; // top l
temp[36] = laf.Y;
temp[37] = 0;
temp[38] = temp[3];
temp[39] = Textures[0].MaxText.Y;
}
break;
}
}
Points = temp;
temp = Array.Empty<float>();
} }
public virtual Vector3i Location public virtual Vector3i Location
@ -687,217 +929,7 @@ public class Rectangle : ITextureObject
} }
set set
{ {
loc_ = value; SetLocation(value.X, value.Y, value.Z);
if (Window is null || Parent is null) return;
float[] temp = Textures.Count == 0
? new float[12]
: TextureDisplay switch
{
TextureDisplay.Clamped => new float[20],
TextureDisplay.HorizontalCenter or TextureDisplay.ProgressHorizontalCenter => new float[40],
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;
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));
temp[0] = saf.X;
temp[(!Textures.Any() ? 3 : 5)] = saf.X;
temp[(!Textures.Any() ? 4 : 6)] = saf.Y;
temp[(!Textures.Any() ? 7 : 11)] = saf.Y;
if (Textures.Count > 0)
{
Vector2i s = Size;
float diff = Window.IntToWindow(s.Y) + 1;
float per = (float)Textures[0].RawSize!.Value.Y / Textures[0].RawSize!.Value.X;
if (TextureDisplay == TextureDisplay.Center)
{
if (s.X > Textures[0].RawSize!.Value.X)
diff = (Window.IntToWindow(Textures[0].RawSize!.Value.X) + 1) / 3;
else
diff = (Window.IntToWindow(s.X) + 1) / 3;
per = Textures[0].MaxText.X / 3;
}
switch (TextureDisplay)
{
case TextureDisplay.Clamped:
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X;
temp[19] = Textures[0].MaxText.Y;
break;
case TextureDisplay.HorizontalCenter:
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X;
temp[19] = Textures[0].MaxText.Y;
temp[20] = saf.X - diff; // top r
temp[21] = laf.Y;
temp[22] = 0;
temp[23] = Textures[0].MaxText.X - per;
temp[24] = 1;
temp[25] = saf.X - diff; // bot r
temp[26] = saf.Y;
temp[27] = 0;
temp[28] = Textures[0].MaxText.X - per;
temp[29] = 0;
temp[30] = laf.X + diff; // bot l
temp[31] = saf.Y;
temp[32] = 0;
temp[33] = per;
temp[34] = 0;
temp[35] = laf.X + diff; // top l
temp[36] = laf.Y;
temp[37] = 0;
temp[38] = per;
temp[39] = 1;
break;
case TextureDisplay.Center:
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X;
temp[19] = Textures[0].MaxText.Y;
int dy, dx;
if (s.Y > Textures[0].RawSize!.Value.Y)
dy = Textures[0].RawSize!.Value.Y;
else
dy = s.Y;
if (s.X > Textures[0].RawSize!.Value.X)
dx = Textures[0].RawSize!.Value.X;
else
dx = s.X;
if (dy > dx) dy = dx;
else dx = dy;
float diffy = (dy + 1) / (float)3;
diff = (dx + 1) / (float)3;
SetPoint(temp, 20, temp[0], temp[1] + diffy, temp[2], temp[3], temp[4] - (temp[4]*per));
SetPoint(temp, 25, temp[0], temp[6] - diffy, temp[2], temp[3], temp[4] * per);
SetPoint(temp, 30, temp[5] - diff, temp[6], temp[2], temp[3] - (temp[3]*per), temp[9]);
SetPoint(temp, 35, temp[10] + diff, temp[6], temp[2], temp[3] * per, temp[9]);
SetPoint(temp, 40, temp[10], temp[26], temp[2], temp[13], temp[29]);
SetPoint(temp, 45, temp[10], temp[21], temp[2], temp[13], temp[24]);
SetPoint(temp, 50, temp[35], temp[1], temp[2], temp[38], temp[4]);
SetPoint(temp, 55, temp[30], temp[1], temp[2], temp[33], temp[4]);
SetPoint(temp, 60, temp[30], temp[21], temp[2], temp[33], temp[24]);
SetPoint(temp, 65, temp[30], temp[26], temp[2], temp[33], temp[29]);
SetPoint(temp, 70, temp[35], temp[26], temp[2], temp[38], temp[29]);
SetPoint(temp, 75, temp[35], temp[21], temp[2], temp[38], temp[24]);
break;
case TextureDisplay.ProgressHorizontalCenter:
if (s.X > s.Y)
{
if (s.X > s.Y + s.Y)
{
temp[3] = Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = Textures[0].MaxText.X;
temp[19] = Textures[0].MaxText.Y;
temp[20] = saf.X - diff; // top r
temp[21] = laf.Y;
temp[22] = 0;
temp[23] = Textures[0].MaxText.X - per;
temp[24] = 1;
temp[25] = saf.X - diff; // bot r
temp[26] = saf.Y;
temp[27] = 0;
temp[28] = 1 - per;
temp[29] = 0;
temp[30] = laf.X + diff; // bot l
temp[31] = saf.Y;
temp[32] = 0;
temp[33] = per;
temp[34] = 0;
temp[35] = laf.X + diff; // top l
temp[36] = laf.Y;
temp[37] = 0;
temp[38] = per;
temp[39] = 1;
}
else
{
temp[3] = (0.666666f + (((s.X - s.Y) / (float)s.Y)* per)) * Textures[0].MaxText.X;
temp[4] = Textures[0].MaxText.Y;
temp[8] = temp[3];
temp[19] = Textures[0].MaxText.Y;
//start last 33% of texture
temp[20] = saf.X; // top r
temp[21] = laf.Y;
temp[22] = 0;
temp[23] = temp[3];
temp[24] = 1;
temp[25] = saf.X; // bot r
temp[26] = saf.Y;
temp[27] = 0;
temp[28] = temp[3];
temp[29] = 0;
temp[30] = laf.X + diff; // bot l
temp[31] = saf.Y;
temp[32] = 0;
temp[33] = per;
temp[34] = 0;
temp[35] = laf.X + diff; // top l
temp[36] = laf.Y;
temp[37] = 0;
temp[38] = per;
temp[39] = 1;
}
}
else
{
//first 33% of texture
temp[3] = ((s.X/(float)s.Y)*per);
temp[4] = Textures[0].MaxText.Y;
temp[8] = temp[3];
temp[19] = Textures[0].MaxText.Y;
temp[20] = saf.X; // top r
temp[21] = laf.Y;
temp[22] = 0;
temp[23] = temp[3];
temp[24] = Textures[0].MaxText.Y;
temp[25] = saf.X; // bot r
temp[26] = saf.Y;
temp[27] = 0;
temp[28] = temp[3];
temp[29] = 0;
temp[30] = saf.X; // bot l
temp[31] = saf.Y;
temp[32] = 0;
temp[33] = temp[3];
temp[34] = 0;
temp[35] = saf.X; // top l
temp[36] = laf.Y;
temp[37] = 0;
temp[38] = temp[3];
temp[39] = Textures[0].MaxText.Y;
}
break;
}
}
Points = temp;
} }
} }

View File

@ -141,10 +141,9 @@ public class TabControl : ParentBase, IParent
} }
} }
public override void ParentResize(ResizeEventArgs e) public override void ParentResize()
{ {
BlockDraw = true; BlockDraw = true;
if (e.Width == 0 && e.Height == 0) return;
if (!(Controls.Length >= PageIndex)) return; if (!(Controls.Length >= PageIndex)) return;
if (!Controls[PageIndex].Loaded) return; if (!Controls[PageIndex].Loaded) return;
bool top = (Controls[PageIndex].Anchor & ObjectAnchor.Top) == ObjectAnchor.Top; 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); Controls[PageIndex].Location = new(lx, ly, Controls[PageIndex].Location.Z);
if (Controls[PageIndex] is IParent parent) if (Controls[PageIndex] is IParent parent)
{ {
parent.ParentResize(e); parent.ParentResize();
} }
for (int i = 0; i < Buttonts.Length; i++) 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); Buttonts[i].Location = new(lx, ly, Buttonts[i].Location.Z);
if (Buttonts[i] is IParent parent2) if (Buttonts[i] is IParent parent2)
{ {
parent2.ParentResize(e); parent2.ParentResize();
} }
} }
Parent!.TryDraw(); Parent!.TryDraw();
@ -201,16 +200,16 @@ public class TabControl : ParentBase, IParent
BlockDraw = false; 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) if (Loaded && Visible)
{ {
base.Draw(x,y,w,h); base.Draw(x,y,sx,sy,sw,sh);
if (!(Controls.Length >= (PageIndex))) return; if (!(Controls.Length >= (PageIndex))) return;
if (!Controls[PageIndex].Loaded) 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++) 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 #version 330
in vec2 in_pos; layout (location = 0) in vec2 in_pos;
in vec2 in_uv; layout (location = 1) in vec2 in_uv;
out vec2 vUV; 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); WindowSizeMatrix = Matrix4.CreateOrthographicOffCenter(0.0f, Size.X, Size.Y, 0, 1, -1);
KeyDown += OnKeyDownn; KeyDown += OnKeyDownn;
TextInput += OnTextInputEvent; TextInput += OnTextInputEvent;
FileDrop += OnFileDrop;
GL.Enable(EnableCap.Blend);
GL.Enable(EnableCap.ScissorTest);
}
private void OnFileDrop(FileDropEventArgs obj)
{
} }
private void OnTextInputEvent(TextInputEventArgs obj) private void OnTextInputEvent(TextInputEventArgs obj)
@ -136,28 +144,20 @@ public class Window : NativeWindow , IWindow
} }
} }
public Window() : this(new NativeWindowSettings()) 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 Vector3i Position { get; } = new(0); public Vector3i Position { get; } = new(0);
public Color4 BackgroundColor { get; set; } = new Color4(0, 0, 0, 255); public Color4 BackgroundColor { get; set; } = new Color4(0, 0, 0, 255);
public ControlList Controls { get; } = new(); 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) public float IntToWindow(float p, bool Y = false)
{ {
return p; return p;
} }
public void ForceUpdate(ResizeEventArgs e) public virtual void ForceUpdate()
{ {
BlockDraw = true; BlockDraw = true;
for (int i = 0; i < Controls.Length; i++) 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; bool bottom = (Controls[i].Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom;
if (!top && !bottom) { Controls[i].Anchor |= ObjectAnchor.Top; top = true; } if (!top && !bottom) { Controls[i].Anchor |= ObjectAnchor.Top; top = true; }
if (!left && !right) { Controls[i].Anchor |= ObjectAnchor.Left; left = 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 lx = (left ? Controls[i].Location.X : CS.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 ly = (top ? Controls[i].Location.Y : CS.Y - Controls[i].Distance.Y - Controls[i].Size.Y);
int sy = (bottom ? Size.Y - Controls[i].Distance.Y - ly : Controls[i].Size.Y); int sy = (bottom ? CS.Y - Controls[i].Distance.Y - ly : Controls[i].Size.Y);
int sx = (right ? Size.X - Controls[i].Distance.X - lx : Controls[i].Size.X); int sx = (right ? CS.X - Controls[i].Distance.X - lx : Controls[i].Size.X);
Controls[i].Size = new(sx, sy); Controls[i].SetSize(sx, sy);
Controls[i].Location = new(lx, ly, Controls[i].Location.Z); Controls[i].SetLocation(lx, ly);
if (Controls[i] is IParent parent) if (Controls[i] is IParent parent)
{ {
parent.ParentResize(e); parent.ParentResize();
} }
} }
DrawFrame(); DrawFrame();
@ -186,15 +186,9 @@ public class Window : NativeWindow , IWindow
public Matrix4 WindowSizeMatrix { get; set; } public Matrix4 WindowSizeMatrix { get; set; }
public void ParentResize(ResizeEventArgs e) public virtual void ParentResize()
{ {
base.OnResize(e); ForceUpdate();
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);
} }
private int frame = 0; 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) 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) protected override void OnClosing(CancelEventArgs e)
@ -233,7 +240,7 @@ public class Window : NativeWindow , IWindow
{ {
ProcessEvents(10); ProcessEvents(10);
} }
public void StartRender() public virtual void StartRender()
{ {
Context.MakeCurrent(); Context.MakeCurrent();
initthread = Thread.CurrentThread.ManagedThreadId; initthread = Thread.CurrentThread.ManagedThreadId;
@ -260,10 +267,12 @@ public class Window : NativeWindow , IWindow
} }
public IRenderObject? HoveringControl { get; set; } public IRenderObject? HoveringControl { get; set; }
public SubHitBox? HoveringHitBox { get; set; }
private void WhenMouseMove(MouseMoveEventArgs obj) private void WhenMouseMove(MouseMoveEventArgs obj)
{ {
IRenderObject? cb = null; IRenderObject? cb = null;
SubHitBox? cbhb = null;
IRenderObject? checkcontrol(IRenderObject render, int add_x = 0, int addy = 0, IRenderObject? CurrentBest = null) IRenderObject? checkcontrol(IRenderObject render, int add_x = 0, int addy = 0, IRenderObject? CurrentBest = null)
{ {
void ClearHoverChain(IRenderObject ChainObject) 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 || 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); CurrentBest = checkcontrol(p.Controls._internal[i], add_x + render.Location.X, addy + render.Location.Y, CurrentBest);
} }
} }
if (CurrentBest is null) if (CurrentBest is null)
{ {
cbhb = null;
CurrentBest = render; CurrentBest = render;
} }
else 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; return CurrentBest;
@ -325,6 +366,19 @@ public class Window : NativeWindow , IWindow
else Cursor = HoverMouse; else Cursor = HoverMouse;
if (old is not null) old.MouseInside = false; 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() public void StartRenderAsync()
@ -357,16 +411,13 @@ public class Window : NativeWindow , IWindow
invokes.Enqueue(A); invokes.Enqueue(A);
} }
public void DrawFrame() public virtual void DrawFrame()
{ {
Context.MakeCurrent(); Context.MakeCurrent();
frame++; frame++;
if (LogFrames) Console.WriteLine($"Drawing Frame: {frame}"); if (LogFrames) Console.WriteLine($"Drawing Frame: {frame}");
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.Enable(EnableCap.ScissorTest);
GL.ClearColor(BackgroundColor.R, BackgroundColor.G, BackgroundColor.B, BackgroundColor.A); GL.ClearColor(BackgroundColor.R, BackgroundColor.G, BackgroundColor.B, BackgroundColor.A);
IEnumerable<IRenderObject> needload = Controls.Where(a => a.Loaded == false); IEnumerable<IRenderObject> needload = Controls.Where(a => a.Loaded == false);
@ -385,9 +436,8 @@ public class Window : NativeWindow , IWindow
{ {
if (!Controls[i].Loaded) continue; if (!Controls[i].Loaded) continue;
GL.Scissor(0, 0, CS.X, CS.Y); 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(); Context.SwapBuffers();
} }
} }