2024-10-10 15:35:19 -04:00

223 lines
6.0 KiB
C#

using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
namespace GraphicsManager.Objects.Core;
public abstract class ParentBase : Rectangle, IParent
{
protected ParentBase(Texture? texture = null)
: base(texture)
{
}
public ControlList Controls { get; } = new();
public int LastX { get; private set; }
public int LastY { get; private set; }
public int LastSX { get; private set; }
public int LastSY { get; private set; }
public int LastSW { get; private set; }
public int LastSH { get; private set; }
public Vector3i Position => Location;
public virtual void ParentResize()
{
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;
if ((Controls[i].Anchor & ObjectAnchor.PreventWidthChange) == ObjectAnchor.PreventWidthChange)
{
UpdateDistance = true;
lx = Controls[i].Location.X + ((Size.X - Controls[i].Distance.X - Controls[i].Size.X - Controls[i].Location.X) / 2);
sx = Controls[i].Size.X;
}
else
{
lx = (left ? Controls[i].Location.X : Size.X - Controls[i].Distance.X - Controls[i].Size.X);
sx = (right ? Size.X - Controls[i].Distance.X - lx : Controls[i].Size.X);
}
if ((Controls[i].Anchor & ObjectAnchor.PreventHeightChange) == ObjectAnchor.PreventHeightChange)
{
UpdateDistance = true;
ly = Controls[i].Location.Y + ((Size.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 : Size.Y - Controls[i].Distance.Y - Controls[i].Size.Y);
sy = (bottom ? Size.Y - Controls[i].Distance.Y - ly : Controls[i].Size.Y);
}
bool mooved = false;
if (sx != Controls[i].Size.X || sy != Controls[i].Size.Y)
{
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 (UpdateDistance)
{
Controls[i].ForceDistanceUpdate(this);
}
if (mooved && Controls[i] is IParent parent)
{
parent.ParentResize();
}
}
if (Parent is not null) Parent.TryDraw();
BlockDraw = false;
}
public virtual void ReportSizeUpdate(IRenderObject Control)
{
}
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 (Location.X - sx + x > sw || Location.Y - sy + y > sh)
{
NotifiNotVisible();
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
{
if (Size.X + Location.X - sx + x < sw)
sw = Size.X + Location.X - sx + x;
}
if (Location.Y - sy + y > -1)
{
int add = Location.Y - sy + y;
sy += add;
sh -= add;
if (Size.Y < sh)
sh = Size.Y;
}
else
{
if (Size.Y + Location.Y - sy + y < sh)
sh = Size.Y + Location.Y - sy + y;
}
x += Location.X;
y += Location.Y;
if (sw <= 0 || sh <= 0)
{
NotifiNotVisible();
return;
}
base.Draw(x,y,sx,sy,sw,sh);
LastX = x;
LastY = y;
LastSX = sx;
LastSY = sy;
LastSW = sw;
LastSH = sh;
IEnumerable<IRenderObject> needload = Controls.Where(a => a.Loaded == false);
if (needload.Any())
{
BlockDraw = true;
foreach (IRenderObject Control in needload)
{
Control.LoadToParent(this, Window!);
}
if (this is IFlow flow) flow.ForceScrollUpdate();
BlockDraw = false;
}
for (int i = 0; i < Controls.Length; i++)
{
if (Controls[i].Location.X > Size.X || Controls[i].Location.Y > Size.Y) continue;
GL.Scissor(sx, Window!.CS.Y - sy - sh, sw, sh);
Controls[i].Draw(x,y,sx,sy,sw,sh);
}
}
}
public bool IgnoreVisForChildren { get; set; }
public override void NotifiNotVisible()
{
base.NotifiNotVisible();
for (int i = 0; i < Controls.Length; i++)
{
Controls[i].NotifiNotVisible();
}
}
public override void Clean()
{
for (int i = 0; i < Controls.Length; i++)
{
Controls[i].Clean();
}
base.Clean();
}
public override void LoadToParent(IParent Parent, IWindow Window)
{
if (Loaded) return;
bool PastBlockState = BlockDraw;
BlockDraw = true;
base.LoadToParent(Parent, Window);
for (int i = 0; i < Controls.Length; i++)
{
if (Controls[i].Loaded) continue;
Controls[i].LoadToParent(this, Window);
if (Controls[i] is IFlow flow) flow.ForceScrollUpdate();
}
BlockDraw = PastBlockState;
}
public override Vector3i Location
{
get => base.Location;
set
{
BlockDraw = true;
base.Location = value;
for (int i = 0; i < Controls.Length; i++)
{
Controls[i].Location = Controls[i].Location;
}
ParentResize();
if (Parent is not null) Parent.TryDraw();
BlockDraw = false;
}
}
public float IntToWindow(float p, bool Y = false)
{
return Parent!.IntToWindow((Y ? this.Location.Y : Location.X), Y) + p;
}
}