2024-11-24 20:38:38 -05:00

665 lines
18 KiB
C#
Executable File

using System.ComponentModel;
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using GraphicsManager.Objects;
using GraphicsManager.Objects.Core;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Common.Input;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.GraphicsLibraryFramework;
namespace GraphicsManager;
public class FPSWindow : GameWindow , IWindow
{
public TextureManager TextureManager { get; private set; }
private TitleBar? _tb = null;
public bool ShowMissingChar { get; set; }
public TitleBar? CustomeTitleBar
{
get => _tb;
set
{
_tb = value;
//some setting/changeing code
}
}
public RenderObjectCore? focused { get; set; }
public bool LogFrames { get; set; } = true;
public int SubFrameCount { get; set; }
public int Frame { get; set; }
public void CenterWindow(int mon)
{
Box2i clientArea = Monitors.GetMonitors()[mon].ClientArea;
int num = (clientArea.Min.X + clientArea.Max.X - Size.X) / 2;
int num2 = (clientArea.Min.Y + clientArea.Max.Y - Size.Y) / 2;
if (num < clientArea.Min.X)
{
num = clientArea.Min.X;
}
if (num2 < clientArea.Min.Y)
{
num2 = clientArea.Min.Y;
}
ClientRectangle = new Box2i(num, num2, num + Size.X, num2 + Size.Y);
}
public Vector2i CS { get; private set; } = new(0, 0);
public Matrix4 WindowSizeMatrix { get; private set; }
public float IntToWindow(float Point, bool Y = false)
{
return Point;
}
public IParent? Parent { get; } = null;
public MouseCursor HoverMouse { get; set; } = MouseCursor.Default;
public Vector2 LocationAsFloat { get; } = new Vector2(0f, 0f);
public FPSWindow(NativeWindowSettings nativeWindowSettings, GameWindowSettings gws) : base(gws,nativeWindowSettings)
{
TextureManager = TextureManager.GetTextureManager(Context, this);
Context.MakeCurrent();
if (!Texture.TextureShader.ContainsKey(Context)) Texture.TextureShader.Add(Context, new("RectangleTexture", true, Texture:true){CanBlend = true});
if (!Rectangle.DefaultShader.ContainsKey(Context)) Rectangle.DefaultShader.Add(Context, new("Rectangle", true));
if (!Rectangle.DefaultAlphaShader.ContainsKey(Context)) Rectangle.DefaultAlphaShader.Add(Context, new("AlphaChannel", true, Texture:true){CanBlend = true});
if (!Rectangle.DefaultAlphaTextureShader.ContainsKey(Context))
{
Rectangle.DefaultAlphaTextureShader.Add(Context, new("AlphaChannelTexture", true, Texture:true){CanBlend = true});
Rectangle.DefaultAlphaTextureShader[Context].Use();
Rectangle.DefaultAlphaTextureShader[Context].SetInt("bob", 0);
Rectangle.DefaultAlphaTextureShader[Context].SetInt("smith", 1);
}
if (!Label.DefaultTextShader.ContainsKey(Context))
{
Label.DefaultTextShader.Add(Context, new("Label", true){CanBlend = true});
Label.DefaultTextShader[Context].Use();
Label.DefaultTextShader[Context].SetInt("u_texture", Label.DefaultTextShader[Context].GetUniformLocation("u_texture"));
}
if (!Label._characters.ContainsKey(Context)) Label._characters.Add(Context, new());
last = WindowState;
WindowSizeMatrix = Matrix4.CreateOrthographicOffCenter(0.0f, Size.X, Size.Y, 0, 1, -1);
KeyDown += OnKeyDownn;
TextInput += OnTextInputEvent;
FileDrop += OnFileDrop;
GL.Enable(EnableCap.Blend);
GL.Enable(EnableCap.ScissorTest);
}
private void OnTextInputEvent(TextInputEventArgs obj)
{
if (focused is not null)
{
focused.SendClipEvent(obj.AsString);
}
}
private WindowState last;
private bool fs = false;
private Vector2i os, loc;
public bool CustomF11 = true;
private unsafe void OnKeyDownn(KeyboardKeyEventArgs obj)
{
if (obj.Key != Keys.F11 || WindowBorder == WindowBorder.Fixed) return;
if (CustomF11)
{
GLFW.WindowHint(WindowHintBool.AutoIconify, true);
if (WindowState != WindowState.Normal) last = WindowState;
switch (fs)
{
case false:
loc = Location;
os = Size;
WindowBorder = WindowBorder.Hidden;
Location = new(4090, 0);
fs = true;
break;
case true:
WindowBorder = WindowBorder.Resizable;
GLFW.RestoreWindow(this.WindowPtr);
Size = os;
Location = loc;
fs = false;
break;
}
}
else
{
switch (fs)
{
case false:
WindowState = WindowState.Fullscreen;
fs = true;
break;
case true:
WindowState = WindowState.Normal;
fs = false;
break;
}
}
}
public FPSWindow() : this(new NativeWindowSettings(), new GameWindowSettings())
{
}
public Vector2i Position { get; } = new(0);
public Color4 BackgroundColor { get; set; } = new Color4(0, 0, 0, 255);
public bool LastFrameIsResize { get; private set; }
public ControlList Controls { get; } = new();
#region Cool Math Things
public float[] RctToFloat(int x, int y, int Width, int Height, bool hasTexture = false, float z = 0.0f)
{
if (hasTexture)
{
return new float[20] {
IntToFloat(x + Width), IntToFloat(y, true), z, 1.0f, 1.0f,// top r
IntToFloat(x + Width), IntToFloat(y + Height, true), z, 1.0f, 0.0f,//b r
IntToFloat(x), IntToFloat(y + Height, true), z, 0.0f, 0.0f,//bot l
IntToFloat(x), IntToFloat(y, true), z, 0.0f, 1.0f// top l
};
}
else
{
return new float[12] {
IntToFloat(x + Width), IntToFloat(y, true), z,// top r
IntToFloat(x + Width), IntToFloat(y + Height, true), z, //b r
IntToFloat(x), IntToFloat(y + Height, true), z, //bot l
IntToFloat(x), IntToFloat(y, true), z,// top l
};
}
}
public Vector3 PointToVector(float x, float y, float z = 0.0f)
{
return new Vector3(IntToFloat(x), IntToFloat(y, true), z);
}
public float IntToFloat(float p, bool Invert = false)
{
float Size = (Invert ? this.Size.Y : this.Size.X);
double half = Math.Round((double)Size / (double)2, 1);
double Per = Math.Round((double)1 / half, 15);
if (p == half) return 0.0f;
if (Invert)
{
if (p > half) return (float)(((double)(p - half) * Per) * -1);
else return (float)(1 - (p * Per));
}
else
{
if (p > half) return (float)((double)(p - half) * Per);
else return (float)((1 - (p * Per)) * -1);
}
}
public float FloatToInt(float p, bool Invert = false)
{
float Size = (Invert ? this.Size.Y : this.Size.X);
double half = Math.Round((double)Size / (double)2, 15);
if (p == 0) return (int)half;
if (Invert)
{
if (p < 0)
{
p *= -1;
p++;
return (float)(half * p);
}
else
{
return (float)(half - (p * half));
}
}
else
{
if (p < 0)
{
p *= -1;
p++;
return (float)(Size - (half * p));
}
else
{
return (float)(p * half + half);
}
}
}
#endregion
public virtual void ForceUpdate(bool resize = false)
{
BlockDraw = true;
for (int i = 0; i < Controls.Length; i++)
{
if (!Controls[i].Loaded) continue;
bool top = (Controls[i].Anchor & ObjectAnchor.Top) == ObjectAnchor.Top;
bool left = (Controls[i].Anchor & ObjectAnchor.Left) == ObjectAnchor.Left;
bool right = (Controls[i].Anchor & ObjectAnchor.Right) == ObjectAnchor.Right;
bool bottom = (Controls[i].Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom;
if (!top && !bottom) { Controls[i].Anchor |= ObjectAnchor.Top; top = true; }
if (!left && !right) { Controls[i].Anchor |= ObjectAnchor.Left; left = true; }
int lx, ly, sy, sx;
bool UpdateDistance = false, SizeChanged = false;
if ((Controls[i].Anchor & ObjectAnchor.PreventWidthChange) == ObjectAnchor.PreventWidthChange)
{
UpdateDistance = true;
lx = Controls[i].Location.X + ((CS.X - Controls[i].Distance.X - Controls[i].Size.X - Controls[i].Location.X) / 2);
sx = Controls[i].Size.X;
}
else
{
SizeChanged = true;
lx = (left ? Controls[i].Location.X : CS.X - Controls[i].Distance.X - Controls[i].Size.X);
sx = (right ? CS.X - Controls[i].Distance.X - lx : Controls[i].Size.X);
}
if ((Controls[i].Anchor & ObjectAnchor.PreventHeightChange) == ObjectAnchor.PreventHeightChange)
{
ly = Controls[i].Location.Y + ((CS.Y - Controls[i].Distance.Y - Controls[i].Size.Y - Controls[i].Location.Y) / 2);
sy = Controls[i].Size.Y;
}
else
{
ly = (top ? Controls[i].Location.Y : CS.Y - Controls[i].Distance.Y - Controls[i].Size.Y);
sy = (bottom ? CS.Y - Controls[i].Distance.Y - ly : Controls[i].Size.Y);
}
if (Controls[i].Size.X != sx && Controls[i].Size.Y != sy)
{
SizeChanged = true;
}
Controls[i].SetSize(sx, sy);
Controls[i].SetLocation(lx, ly);
if (UpdateDistance)
{
Controls[i].ForceDistanceUpdate(this);
}
if (Controls[i] is IParent parent && SizeChanged)
{
parent.ParentResize();
}
}
if (resize) ResizeFrameP1();
else FrameP1();
CheckParent(this);
LastFrameIsResize = true;
BlockDraw = false;
}
public virtual void ResizeFrameP1()
{
Context.MakeCurrent();
Frame++;
if (LogFrames) Console.WriteLine($"Drawing Frame: {Frame}");
SubFrameCount = 0;
DrawNewResizeFrameToBackBuffer();
Context.SwapBuffers();
}
public virtual void DrawNewResizeFrameToBackBuffer()
{
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.ClearColor(BackgroundColor.R, BackgroundColor.G, BackgroundColor.B, BackgroundColor.A);
LastSW = CS.X;
LastSH = CS.Y;
GL.Scissor(0,0,CS.X, CS.Y);
GL.Clear(ClearBufferMask.ColorBufferBit);
for (int i = 0; i < Controls.Length; i++)
{
if (!Controls[i].Loaded)
{
BlockDraw = true;
Controls[i].LoadToParent(this, this);
BlockDraw = false;
}
if (Controls[i].Location.X >= CS.X ||
Controls[i].Location.Y >= CS.Y ||
Controls[i].Location.X + Controls[i].Size.X < 0 ||
Controls[i].Location.Y + Controls[i].Size.Y < 0) continue;
if (Controls[i] is ParentBase p)
{
p.Draw(0, 0, 0, 0, CS.X, CS.Y);
GL.Scissor(0, 0, CS.X, CS.Y);
}
else
{
Controls[i].DrawSelf();
}
}
}
public void ParentResize()
{
ForceUpdate(true);
}
public virtual void ResizeDraw(int x, int y, int sx, int sy, int sw, int sh)
{
}
public int OldWidth { get; }
public int OldHeight { get; }
public void CopyFromFrontToBack()
{
CopyFromFrontToBack(0, 0, CS.X, CS.Y, 0, 0);
}
public virtual void CopyFromFrontToBack(int x, int y, int width, int height, int NewX, int NewY)
{
int sourceY1 = CS.Y - y - height;
int sourceX2 = x + width;
int sourceY2 = CS.Y - y;
int destY1 = CS.Y - NewY - height;
int destX2 = NewX + width;
int destY2 = destY1 + height;
GL.ReadBuffer(ReadBufferMode.Front);
GL.DrawBuffer(DrawBufferMode.Back);
GL.BlitFramebuffer(
x, sourceY1, sourceX2, sourceY2,
NewX, destY1, destX2, destY2,
ClearBufferMask.ColorBufferBit,
BlitFramebufferFilter.Nearest
);
}
private int frame = 0;
public bool UseLiveView { get; set; } = false;
public bool CollectUpperFiles { get; set; }
public void ReportSizeUpdate(RenderObjectCore Control)
{
}
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)
{
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)
{
Context.MakeCurrent();
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindVertexArray(0);
GL.UseProgram(0);
for (int i = 0; i < Controls.Length; i++)
{
Controls[i].Clean();
}
base.OnClosing(e);
}
public Rendertype Rendertype { get; set; } = Rendertype.ControlUpdates;
public bool CanControleUpdate { get; set; } = true;
public int FPS { get; set; } = 0;
public event Func<FPSWindow, Task>? WindowLoaded;
public List<Window> Windows = new();
public RenderObjectCore? HoveringControl { get; set; }
private void WhenMouseMove(MouseMoveEventArgs obj)
{
HoverCheck(obj);
}
protected virtual void HoverCheck(MouseMoveEventArgs obj)
{
RenderObjectCore? cb = null;
SubHitBox? cbhb = null;
RenderObjectCore? checkcontrol(RenderObjectCore render, int add_x = 0, int addy = 0, RenderObjectCore? CurrentBest = null)
{
void ClearHoverChain(RenderObjectCore ChainObject)
{
if (ChainObject is IParent parent)
{
for (int i = 0; i < parent.Controls.Length; i++)
{
ClearHoverChain(parent.Controls._internal[i]);
}
}
if (ChainObject.AllowHoverFromBehind)
{
ChainObject.MouseInside = false;
if (ChainObject.SubHitBoxes.Count > 0)
{
foreach (SubHitBox shb in ChainObject.SubHitBoxes)
{
shb.MouseInside = false;
}
}
}
}
if (!render.Visible ||
render.IgnoreHover ||
render.Location.X + add_x > obj.X ||
render.Location.Y + addy > obj.Y ||
render.Location.X + render.Size.X + add_x < obj.X ||
render.Location.Y + render.Size.Y + addy < obj.Y)
{
ClearHoverChain(render);
return CurrentBest;
}
if (render.AllowHoverFromBehind) render.MouseInside = true;
if (render is IParent p)
{
for (int i = p.Controls.Length - 1; i >= 0; i--)
{
CurrentBest = checkcontrol(p.Controls._internal[i], add_x + render.Location.X, addy + render.Location.Y, CurrentBest);
}
}
if (CurrentBest is null)
{
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;
}
for (int i = Controls.Length - 1; i >= 0; i--)
{
cb = checkcontrol(Controls._internal[i],0,0,cb);
}
if (cb != HoveringControl)
{
RenderObjectCore? old = HoveringControl;
HoveringControl = cb;
if (cb is not null)
{
cb.MouseInside = true;
Cursor = cb.HoverMouse;
}
else Cursor = HoverMouse;
if (old is not null) old.MouseInside = false;
}
if (cbhb != HoveringHitBox)
{
SubHitBox? old = HoveringHitBox;
HoveringHitBox = cbhb;
if (cbhb is not null)
{
cbhb.MouseInside = true;
Cursor = cbhb.HoverMouse;
}
else Cursor = HoverMouse;
if (old is not null) old.MouseInside = false;
}
}
public SubHitBox? HoveringHitBox { get; set; }
public bool BlockDraw { get; set; }
public void TryDraw(int depth = 0)
{
}
public bool IgnoreVisForChildren { get; set; }
public const float alpha = 254f / byte.MaxValue;
public virtual void CheckParent(IParent p, RenderObjectCore c, int xx, Vector2i di)
{
if (p.IgnoreVisForChildren || p.Controls.Length <= 1 || xx >= p.Controls.Length || !c.Visible || c is LabelBase || (c is Rectangle r && r.BackgroundColor.A <= alpha)) return;
for (int i = xx; i > 0; i--)
{
if (!p.Controls[i].IsVisible ||
((p.Controls[i].Location.X + di.X >= c.Location.X && p.Controls[i].Location.X + p.Controls[i].Size.X + di.X - c.Size.X <= c.Location.X) &&
(p.Controls[i].Location.Y + di.Y >= c.Location.Y && p.Controls[i].Location.Y + p.Controls[i].Size.Y + di.X - c.Size.Y <= c.Location.Y)))
{
p.Controls[i].NotifiNotVisible();
continue;
}
if (p.Controls[i] is IParent pp) CheckParent(pp, c, pp.Controls.Length-1, di + p.Controls[i].Location);
}
}
public virtual void CheckParent(IParent p)
{
for (int i = p.Controls.Length - 1; i > 0; i--)
{
CheckParent(p, p.Controls[i], i-1, new());
if (p.Controls[i] is IParent pp) CheckParent(pp);
}
}
private int initthread;
public bool InvokeRequired
{
get
{
return initthread != Thread.CurrentThread.ManagedThreadId;
}
}
private Queue<Action> invokes = new();
public int LastX { get; } = 0;
public int LastY { get; } = 0;
public int LastSX { get; } = 0;
public int LastSY { get; } = 0;
public int LastSW { get; set; } = 0;
public int LastSH { get; set; } = 0;
public void Invoke(Action A)
{
invokes.Enqueue(A);
}
public virtual void DrawNewFrameToBackBuffer()
{
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.ClearColor(BackgroundColor.R, BackgroundColor.G, BackgroundColor.B, BackgroundColor.A);
LastSW = CS.X;
LastSH = CS.Y;
GL.Scissor(0,0,CS.X, CS.Y);
GL.Clear(ClearBufferMask.ColorBufferBit);
for (int i = 0; i < Controls.Length; i++)
{
if (!Controls[i].Loaded)
{
BlockDraw = true;
Controls[i].LoadToParent(this, this);
BlockDraw = false;
}
if (Controls[i].Location.X >= CS.X ||
Controls[i].Location.Y >= CS.Y ||
Controls[i].Location.X + Controls[i].Size.X < 0 ||
Controls[i].Location.Y + Controls[i].Size.Y < 0) continue;
if (Controls[i] is ParentBase p)
{
p.Draw(0, 0, 0, 0, CS.X, CS.Y);
GL.Scissor(0, 0, CS.X, CS.Y);
}
else
{
Controls[i].DrawSelf();
}
}
}
public virtual void FrameP1()
{
Context.MakeCurrent();
Frame++;
if (LogFrames) Console.WriteLine($"Drawing Frame: {Frame}");
SubFrameCount = 0;
DrawNewFrameToBackBuffer();
Context.SwapBuffers();
}
public bool UseSubFrames { get; set; } = false;
protected override void OnRenderFrame(FrameEventArgs args)
{
if (invokes.Any())
{
for (int i = 0; i < invokes.Count; i++) invokes.Dequeue().Invoke();
}
FrameP1();
if (LastFrameIsResize)
{
DrawNewFrameToBackBuffer();
LastFrameIsResize = false;
}
CheckParent(this);
}
}