Rendering Optimizations
This commit is contained in:
parent
3595cfc27d
commit
ec6d6064b1
@ -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);
|
||||||
|
@ -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' ">
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 = "-")
|
||||||
@ -32,7 +34,6 @@ public class FontFamily
|
|||||||
};
|
};
|
||||||
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();
|
{
|
||||||
|
using (var ss = font.Open())
|
||||||
|
{
|
||||||
|
using (var memoryStream = new MemoryStream())
|
||||||
|
{
|
||||||
ss.CopyTo(memoryStream);
|
ss.CopyTo(memoryStream);
|
||||||
|
byte[] fontBytes = memoryStream.ToArray();
|
||||||
|
|
||||||
if (i)
|
if (i)
|
||||||
{
|
{
|
||||||
if (!f.SInternalFontsi.ContainsKey(s))
|
if (!f.InternalFontsi.ContainsKey(s))
|
||||||
f.SInternalFontsi.Add(s, new(memoryStream, null));
|
{
|
||||||
|
f.InternalFontsi.Add(s, Font.MakeFontFromByteArray(fontBytes));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!f.SInternalFonts.ContainsKey(s))
|
if (!f.InternalFonts.ContainsKey(s))
|
||||||
f.SInternalFonts.Add(s, new(memoryStream, null));
|
{
|
||||||
|
f.InternalFonts.Add(s, Font.MakeFontFromByteArray(fontBytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string p = FontPath;
|
||||||
|
if (!Directory.Exists(p)) Directory.CreateDirectory(p);
|
||||||
|
p = Path.Combine(p, "GM_Familys");
|
||||||
|
if (!Directory.Exists(p)) Directory.CreateDirectory(p);
|
||||||
|
p = Path.Combine(p, Family);
|
||||||
|
if (!Directory.Exists(p)) Directory.CreateDirectory(p);
|
||||||
|
p = Path.Combine(p, Path.GetRandomFileName());
|
||||||
|
font.ExtractToFile(p, true);
|
||||||
|
if (i)
|
||||||
|
{
|
||||||
|
if (!f.InternalFontsi.ContainsKey(s))
|
||||||
|
{
|
||||||
|
f.InternalFontsi.Add(s, Font.MakeFontFromFile(p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!f.InternalFonts.ContainsKey(s))
|
||||||
|
{
|
||||||
|
f.InternalFonts.Add(s, Font.MakeFontFromFile(p));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ss.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd.EndsWith("italic"))
|
if (fd.EndsWith("italic"))
|
||||||
@ -84,7 +122,7 @@ public class FontFamily
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
FamilyZip.Dispose();
|
FamilyZip.Dispose();
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,112 +72,26 @@ 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].SInternalFontsi.TryGetValue(FontSize, out Tuple<MemoryStream, Font?>? f))
|
if (Families_[j].InternalFontsi.TryGetValue(FontSize, out Font? f))
|
||||||
{
|
{
|
||||||
i = value;
|
i = value;
|
||||||
if (f.Item2 is null)
|
CurrentFonts[j] = (Families_[j].InternalFontsi[fs]);
|
||||||
{
|
|
||||||
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();
|
if (ReloadUI is not null) ReloadUI.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Families_[j].SInternalFonts.TryGetValue(FontSize, out Tuple<MemoryStream, Font?>? f))
|
if (Families_[j].InternalFonts.TryGetValue(FontSize, out Font? f))
|
||||||
{
|
{
|
||||||
i = value;
|
i = value;
|
||||||
if (f.Item2 is null)
|
CurrentFonts[j] = Families_[j].InternalFonts[fs];
|
||||||
{
|
|
||||||
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();
|
if (ReloadUI is not null) ReloadUI.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
if (Families_[j].InternalFontsi.TryGetValue(FontSize, out Tuple<string, Font?>? f))
|
|
||||||
{
|
|
||||||
i = value;
|
|
||||||
if (f.Item2 is null)
|
|
||||||
{
|
|
||||||
switch (Italic)
|
|
||||||
{
|
|
||||||
case true:
|
|
||||||
Families_[j].InternalFontsi[fs] = new(f.Item1,
|
|
||||||
Font.MakeFontFromFile(Families_[j].InternalFontsi[fs].Item1));
|
|
||||||
break;
|
|
||||||
case false:
|
|
||||||
Families_[j].InternalFonts[fs] = new(f.Item1,
|
|
||||||
Font.MakeFontFromFile(Families_[j].InternalFonts[fs].Item1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentFonts[j] = (Families_[j].InternalFontsi[fs].Item2!);
|
|
||||||
if (ReloadUI is not null) ReloadUI.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Families_[j].InternalFonts.TryGetValue(FontSize, out Tuple<string, Font?>? f))
|
|
||||||
{
|
|
||||||
i = value;
|
|
||||||
if (f.Item2 is null)
|
|
||||||
{
|
|
||||||
switch (Italic)
|
|
||||||
{
|
|
||||||
case true:
|
|
||||||
Families_[j].InternalFontsi[fs] = new(f.Item1,
|
|
||||||
Font.MakeFontFromFile(Families_[j].InternalFontsi[fs].Item1));
|
|
||||||
break;
|
|
||||||
case false:
|
|
||||||
Families_[j].InternalFonts[fs] = new(f.Item1,
|
|
||||||
Font.MakeFontFromFile(Families_[j].InternalFonts[fs].Item1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentFonts[j] = Families_[j].InternalFonts[fs].Item2!;
|
|
||||||
if (ReloadUI is not null) ReloadUI.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,9 +99,7 @@ public class FontInteraction
|
|||||||
private static Tuple<string, Font?> gcl(Dictionary<FontSize, Tuple<string, Font?>> thisList, FontSize thisValue, out FontSize fs)
|
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,62 +128,18 @@ 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!,
|
true => Families_[j].InternalFontsi[fs],
|
||||||
false => Families_[j].SInternalFonts[fs].Item2!,
|
false => Families_[j].InternalFonts[fs],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Tuple<string, Font?> f = Italic switch
|
|
||||||
{
|
|
||||||
true => gcl(Families_[j].InternalFontsi, value, out fs),
|
|
||||||
false => gcl(Families_[j].InternalFonts, value, out fs),
|
|
||||||
};
|
|
||||||
if (f.Item2 is null)
|
|
||||||
{
|
|
||||||
switch (Italic)
|
|
||||||
{
|
|
||||||
case true:
|
|
||||||
Families_[j].InternalFontsi[fs] = new(f.Item1,
|
|
||||||
Font.MakeFontFromFile(Families_[j].InternalFontsi[fs].Item1));
|
|
||||||
break;
|
|
||||||
case false:
|
|
||||||
Families_[j].InternalFonts[fs] =
|
|
||||||
new(f.Item1, Font.MakeFontFromFile(Families_[j].InternalFonts[fs].Item1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CurrentFonts[j] = Italic switch
|
|
||||||
{
|
|
||||||
true => Families_[j].InternalFontsi[fs].Item2!,
|
|
||||||
false => Families_[j].InternalFonts[fs].Item2!,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ReloadUI is not null) ReloadUI.Invoke();
|
if (ReloadUI is not null) ReloadUI.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
623
GraphicsManager/Objects/Core/LabelBase.cs
Normal file
623
GraphicsManager/Objects/Core/LabelBase.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
|
||||||
|
if (Location.X - sx + x > -1)
|
||||||
|
{
|
||||||
|
int add = Location.X - sx + x;
|
||||||
|
sx += add;
|
||||||
|
sw -= add;
|
||||||
|
if (Size.X < sw)
|
||||||
|
sw = Size.X;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nx += Location.X;
|
if (Size.X + Location.X - sx + x < sw)
|
||||||
nw -= Location.X;
|
sw = Size.X + Location.X - sx + x;
|
||||||
if (Size.X < nw)
|
}
|
||||||
nw = Size.X;
|
if (Location.Y - sy + y > -1)
|
||||||
|
{
|
||||||
|
int add = Location.Y - sy + y;
|
||||||
|
sy += add;
|
||||||
|
sh -= add;
|
||||||
|
if (Size.Y < sh)
|
||||||
|
sh = Size.Y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Size.Y + Location.Y - sy + y < sh)
|
||||||
|
sh = Size.Y + Location.Y - sy + y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Location.Y > nh)
|
x += Location.X;
|
||||||
return;
|
y += Location.Y;
|
||||||
else
|
|
||||||
{
|
if (sw <= 0 || sh <= 0) return;
|
||||||
if (Location.Y > -1)
|
base.Draw(x,y,sx,sy,sw,sh);
|
||||||
{
|
|
||||||
ny += Location.Y;
|
|
||||||
nh -= Location.Y;
|
|
||||||
if (Size.Y < nh)
|
|
||||||
nh = Size.Y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Size.Y + Location.Y < nh)
|
|
||||||
nh = Size.Y + Location.Y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nw == 0 || nh == 0) return;
|
|
||||||
GL.Scissor(nx, Window!.CS.Y - ny - nh, nw, nh);
|
|
||||||
base.Draw(nx,ny,nw,nh);
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
41
GraphicsManager/Objects/Core/SubHitBox.cs
Normal file
41
GraphicsManager/Objects/Core/SubHitBox.cs
Normal 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}}}";
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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; }
|
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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,10 +460,20 @@ public class Rectangle : ITextureObject
|
|||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
size_ = value;
|
SetSize(value.X, value.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SetSize(int wh)
|
||||||
|
{
|
||||||
|
SetSize(wh, wh);
|
||||||
|
}
|
||||||
|
public virtual void SetSize(int w, int h)
|
||||||
|
{
|
||||||
|
size_.X = w;
|
||||||
|
size_.Y = h;
|
||||||
if (Window is null || Parent is null) return;
|
if (Window is null || Parent is null) return;
|
||||||
Parent.ReportSizeUpdate(this);
|
Parent.ReportSizeUpdate(this);
|
||||||
//float[] temp = Points;
|
|
||||||
float[] temp = Textures.Count == 0
|
float[] temp = Textures.Count == 0
|
||||||
? new float[12]
|
? new float[12]
|
||||||
: TextureDisplay switch
|
: TextureDisplay switch
|
||||||
@ -469,7 +483,8 @@ public class Rectangle : ITextureObject
|
|||||||
TextureDisplay.Center => new float[80],
|
TextureDisplay.Center => new float[80],
|
||||||
_ => new float[20]
|
_ => new float[20]
|
||||||
};
|
};
|
||||||
saf = new Vector2(Parent.IntToWindow(value.X + loc_.X, false), Parent.IntToWindow(value.Y + loc_.Y, true));
|
saf.X = Parent.IntToWindow(w + loc_.X);
|
||||||
|
saf.Y = Parent.IntToWindow(h + loc_.Y, true);
|
||||||
temp[2] = Location.Z;
|
temp[2] = Location.Z;
|
||||||
temp[(!Textures.Any() ? 5 : 7)] = Location.Z;
|
temp[(!Textures.Any() ? 5 : 7)] = Location.Z;
|
||||||
temp[(!Textures.Any() ? 8 : 12)] = Location.Z;
|
temp[(!Textures.Any() ? 8 : 12)] = Location.Z;
|
||||||
@ -486,17 +501,16 @@ public class Rectangle : ITextureObject
|
|||||||
|
|
||||||
if (Textures.Count > 0)
|
if (Textures.Count > 0)
|
||||||
{
|
{
|
||||||
Vector2i s = value;
|
float diff = Window.IntToWindow(h) + 1;
|
||||||
float diff = Window.IntToWindow(s.Y) + 1;
|
|
||||||
float per = (float)Textures[0].RawSize!.Value.Y / Textures[0].RawSize!.Value.X;
|
float per = (float)Textures[0].RawSize!.Value.Y / Textures[0].RawSize!.Value.X;
|
||||||
if (TextureDisplay == TextureDisplay.TextureHorizontalCenter)
|
if (TextureDisplay == TextureDisplay.TextureHorizontalCenter)
|
||||||
diff = Window.IntToWindow(Textures[0].RawSize!.Value.Y);
|
diff = Window.IntToWindow(Textures[0].RawSize!.Value.Y);
|
||||||
if (TextureDisplay == TextureDisplay.Center)
|
if (TextureDisplay == TextureDisplay.Center)
|
||||||
{
|
{
|
||||||
if (s.X > Textures[0].RawSize!.Value.X)
|
if (w> Textures[0].RawSize!.Value.X)
|
||||||
diff = (Window.IntToWindow(Textures[0].RawSize!.Value.X) + 1) / 3;
|
diff = (Window.IntToWindow(Textures[0].RawSize!.Value.X) + 1) / 3;
|
||||||
else
|
else
|
||||||
diff = (Window.IntToWindow(s.X) + 1) / 3;
|
diff = (Window.IntToWindow(w) + 1) / 3;
|
||||||
per = Textures[0].MaxText.X / 3;
|
per = Textures[0].MaxText.X / 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,14 +558,14 @@ public class Rectangle : ITextureObject
|
|||||||
temp[19] = Textures[0].MaxText.Y;
|
temp[19] = Textures[0].MaxText.Y;
|
||||||
|
|
||||||
int dy, dx;
|
int dy, dx;
|
||||||
if (s.Y > Textures[0].RawSize!.Value.Y)
|
if (h > Textures[0].RawSize!.Value.Y)
|
||||||
dy = Textures[0].RawSize!.Value.Y;
|
dy = Textures[0].RawSize!.Value.Y;
|
||||||
else
|
else
|
||||||
dy = s.Y;
|
dy = h;
|
||||||
if (s.X > Textures[0].RawSize!.Value.X)
|
if (w > Textures[0].RawSize!.Value.X)
|
||||||
dx = Textures[0].RawSize!.Value.X;
|
dx = Textures[0].RawSize!.Value.X;
|
||||||
else
|
else
|
||||||
dx = s.X;
|
dx = w;
|
||||||
|
|
||||||
if (dy > dx) dy = dx;
|
if (dy > dx) dy = dx;
|
||||||
else dx = dy;
|
else dx = dy;
|
||||||
@ -575,9 +589,9 @@ public class Rectangle : ITextureObject
|
|||||||
SetPoint(temp, 75, temp[35], temp[21], temp[2], temp[38], temp[24]);
|
SetPoint(temp, 75, temp[35], temp[21], temp[2], temp[38], temp[24]);
|
||||||
break;
|
break;
|
||||||
case TextureDisplay.ProgressHorizontalCenter:
|
case TextureDisplay.ProgressHorizontalCenter:
|
||||||
if (s.X > s.Y)
|
if (w > h)
|
||||||
{
|
{
|
||||||
if (s.X > s.Y + s.Y)
|
if (w > h+ h)
|
||||||
{
|
{
|
||||||
temp[3] = Textures[0].MaxText.X;
|
temp[3] = Textures[0].MaxText.X;
|
||||||
temp[4] = Textures[0].MaxText.Y;
|
temp[4] = Textures[0].MaxText.Y;
|
||||||
@ -609,7 +623,7 @@ public class Rectangle : ITextureObject
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
temp[3] = (0.666666f + (((s.X - s.Y) / (float)s.Y)* per)) * Textures[0].MaxText.X;
|
temp[3] = (0.666666f + (((w - h) / (float)h)* per)) * Textures[0].MaxText.X;
|
||||||
temp[4] = Textures[0].MaxText.Y;
|
temp[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;
|
||||||
@ -642,7 +656,7 @@ public class Rectangle : ITextureObject
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//first 33% of texture
|
//first 33% of texture
|
||||||
temp[3] = ((s.X/(float)s.Y)*per);
|
temp[3] = ((w/(float)h)*per);
|
||||||
temp[4] = Textures[0].MaxText.Y;
|
temp[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;
|
||||||
@ -675,19 +689,23 @@ public class Rectangle : ITextureObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
Points = temp;
|
Points = temp;
|
||||||
|
temp = Array.Empty<float>();
|
||||||
if (SizeChanged is not null) SizeChanged.Invoke(this);
|
if (SizeChanged is not null) SizeChanged.Invoke(this);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public virtual Vector3i Location
|
public virtual void SetLocation(int x, int y)
|
||||||
{
|
{
|
||||||
get
|
SetLocation(x, y, Location.Z);
|
||||||
{
|
|
||||||
return loc_;
|
|
||||||
}
|
}
|
||||||
set
|
public virtual void SetLocation(int xy)
|
||||||
{
|
{
|
||||||
loc_ = value;
|
SetLocation(xy, xy, 0);
|
||||||
|
}
|
||||||
|
public virtual void SetLocation(int x, int y, int z)
|
||||||
|
{
|
||||||
|
loc_.X = x;
|
||||||
|
loc_.Y = y;
|
||||||
|
loc_.Z = z;
|
||||||
if (Window is null || Parent is null) return;
|
if (Window is null || Parent is null) return;
|
||||||
float[] temp = Textures.Count == 0
|
float[] temp = Textures.Count == 0
|
||||||
? new float[12]
|
? new float[12]
|
||||||
@ -698,17 +716,19 @@ public class Rectangle : ITextureObject
|
|||||||
TextureDisplay.Center => new float[80],
|
TextureDisplay.Center => new float[80],
|
||||||
_ => new float[20]
|
_ => new float[20]
|
||||||
};
|
};
|
||||||
laf = new Vector2(Parent.IntToWindow(value.X, false), Parent.IntToWindow(value.Y, true));
|
laf.X = Parent.IntToWindow(x);
|
||||||
temp[2] = value.Z;
|
laf.Y = Parent.IntToWindow(y, true);
|
||||||
temp[(!Textures.Any() ? 5 : 7)] = value.Z;
|
temp[2] = z;
|
||||||
temp[(!Textures.Any() ? 8 : 12)] = value.Z;
|
temp[(!Textures.Any() ? 5 : 7)] = z;
|
||||||
temp[(!Textures.Any() ? 11 : 17)] = value.Z;
|
temp[(!Textures.Any() ? 8 : 12)] = z;
|
||||||
|
temp[(!Textures.Any() ? 11 : 17)] = z;
|
||||||
|
|
||||||
temp[(!Textures.Any() ? 6 : 10)] = laf.X;
|
temp[(!Textures.Any() ? 6 : 10)] = laf.X;
|
||||||
temp[(!Textures.Any() ? 9 : 15)] = laf.X;
|
temp[(!Textures.Any() ? 9 : 15)] = laf.X;
|
||||||
temp[1] = laf.Y;
|
temp[1] = laf.Y;
|
||||||
temp[(!Textures.Any() ? 10 : 16)] = laf.Y;
|
temp[(!Textures.Any() ? 10 : 16)] = laf.Y;
|
||||||
saf = new Vector2(Parent.IntToWindow(Size.X + value.X, false), Parent.IntToWindow(Size.Y + value.Y, true));
|
saf.X = Parent.IntToWindow(Size.X + x);
|
||||||
|
saf.Y = Parent.IntToWindow(Size.Y + y, true);
|
||||||
temp[0] = saf.X;
|
temp[0] = saf.X;
|
||||||
temp[(!Textures.Any() ? 3 : 5)] = saf.X;
|
temp[(!Textures.Any() ? 3 : 5)] = saf.X;
|
||||||
temp[(!Textures.Any() ? 4 : 6)] = saf.Y;
|
temp[(!Textures.Any() ? 4 : 6)] = saf.Y;
|
||||||
@ -898,6 +918,18 @@ public class Rectangle : ITextureObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Points = temp;
|
Points = temp;
|
||||||
|
temp = Array.Empty<float>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Vector3i Location
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return loc_;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetLocation(value.X, value.Y, value.Z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user