Finally!
After a long time, I have a basic library for handling OpenGL with no errors to my knowledge.
This commit is contained in:
parent
a6b2fae045
commit
91db2b6471
10
GraphicsManager/Enums/ObjectAnchor.cs
Normal file
10
GraphicsManager/Enums/ObjectAnchor.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace GraphicsManager.Enums;
|
||||||
|
|
||||||
|
public enum ObjectAnchor
|
||||||
|
{
|
||||||
|
Left = 0b_0001,
|
||||||
|
Top = 0b_0010,
|
||||||
|
Right = 0b_0100,
|
||||||
|
Bottom = 0b_1000,
|
||||||
|
All = Left | Top | Right | Bottom,
|
||||||
|
}
|
20
GraphicsManager/GraphicsManager.csproj
Normal file
20
GraphicsManager/GraphicsManager.csproj
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Resources/**"></EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="OpenTK" Version="4.7.1" />
|
||||||
|
<PackageReference Include="SharpFontCore" Version="0.1.1" />
|
||||||
|
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
|
||||||
|
<PackageReference Include="SpaceWizards.SharpFont" Version="1.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
18
GraphicsManager/Interfaces/IParent.cs
Normal file
18
GraphicsManager/Interfaces/IParent.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Common;
|
||||||
|
|
||||||
|
namespace GraphicsManager.Interfaces;
|
||||||
|
|
||||||
|
public interface IParent
|
||||||
|
{
|
||||||
|
public Vector2i Size { get; }
|
||||||
|
public void Resize(ResizeEventArgs e);
|
||||||
|
public float[] RctToFloat(int x, int y, int Width, int Height, bool hastexture = false, float z = 0.0f);
|
||||||
|
public float IntToFloat(int p, bool Invert = false);
|
||||||
|
public float FloatToInt(float p, bool Invert = false);
|
||||||
|
public event Action<MouseButtonEventArgs> MouseDown;
|
||||||
|
public event Action<KeyboardKeyEventArgs> KeyDown;
|
||||||
|
public Vector2 MousePosition { get; }
|
||||||
|
|
||||||
|
public Vector2i Position { get; }
|
||||||
|
}
|
23
GraphicsManager/Interfaces/IRenderObject.cs
Normal file
23
GraphicsManager/Interfaces/IRenderObject.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace GraphicsManager.Interfaces;
|
||||||
|
|
||||||
|
public interface IRenderObject
|
||||||
|
{
|
||||||
|
public ObjectAnchor Anchor { get; set; }
|
||||||
|
public bool Loaded { get; }
|
||||||
|
public void LoadToParent(IParent Parent, Window Window);
|
||||||
|
public void Draw();
|
||||||
|
public void Clean();
|
||||||
|
public Vector2i Size { get; set; }
|
||||||
|
public Vector2i Location { get; set; }
|
||||||
|
public Vector2 SizeAsFloat { get; }
|
||||||
|
public Vector2 LocationAsFloat { get; }
|
||||||
|
public Vector2i Distance { get; }
|
||||||
|
public IParent? Parent { get; }
|
||||||
|
public Window? Window { get; }
|
||||||
|
public bool Visible { get; set; }
|
||||||
|
|
||||||
|
public event Func<IRenderObject, Task>? Clicked;
|
||||||
|
}
|
13
GraphicsManager/Interfaces/ITextureObject.cs
Normal file
13
GraphicsManager/Interfaces/ITextureObject.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace GraphicsManager.Interfaces;
|
||||||
|
|
||||||
|
public interface ITextureObject : IRenderObject
|
||||||
|
{
|
||||||
|
public Texture? Texture { get; }
|
||||||
|
}
|
59
GraphicsManager/Objects/Core/Font.cs
Normal file
59
GraphicsManager/Objects/Core/Font.cs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace GraphicsManager.Objects.Core;
|
||||||
|
|
||||||
|
public class Font
|
||||||
|
{
|
||||||
|
public void SetEmbeddedFont(string Font, Assembly? Assembly = null)
|
||||||
|
{
|
||||||
|
_ = Font ?? throw new ArgumentNullException(nameof(Font));
|
||||||
|
this.Assembly = Assembly;
|
||||||
|
this.Embeded = true;
|
||||||
|
this.Name = Font;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Font MakeEmbeddedFont(string Font, Assembly? Assembly = null)
|
||||||
|
{
|
||||||
|
_ = Font ?? throw new ArgumentNullException(nameof(Font));
|
||||||
|
return new Font()
|
||||||
|
{
|
||||||
|
Assembly = Assembly,
|
||||||
|
Embeded = true,
|
||||||
|
Name = Font,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Font MakeFontFromFile(string Font)
|
||||||
|
{
|
||||||
|
_ = Font ?? throw new ArgumentNullException(nameof(Font));
|
||||||
|
return new Font()
|
||||||
|
{
|
||||||
|
Assembly = null,
|
||||||
|
Embeded = false,
|
||||||
|
Name = Font,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFontFile(string Font)
|
||||||
|
{
|
||||||
|
_ = Font ?? throw new ArgumentNullException(nameof(Font));
|
||||||
|
this.Assembly = null;
|
||||||
|
this.Embeded = false;
|
||||||
|
this.Name = Font;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] GetData()
|
||||||
|
{
|
||||||
|
if (Embeded)
|
||||||
|
{
|
||||||
|
string Base = "GraphicsManager.Resources.Fonts.";
|
||||||
|
if (Assembly is not null) Base = string.Empty;
|
||||||
|
return (Assembly is null ? Tools.GetResourceBytes(Base + Name) : Tools.GetResourceBytes(Assembly!, $"{Base}{Name}"));
|
||||||
|
}
|
||||||
|
return File.ReadAllBytes(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; private set; } = "shal be default";
|
||||||
|
public bool Embeded { get; private set; }
|
||||||
|
public Assembly? Assembly { get; private set; }
|
||||||
|
}
|
129
GraphicsManager/Objects/Core/Shader.cs
Normal file
129
GraphicsManager/Objects/Core/Shader.cs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace GraphicsManager.Objects.Core;
|
||||||
|
|
||||||
|
public class Shader : IDisposable
|
||||||
|
{
|
||||||
|
public int Handle { get; }
|
||||||
|
private readonly int VertexShader;
|
||||||
|
private readonly int FragmentShader;
|
||||||
|
private bool disposedValue = false;
|
||||||
|
|
||||||
|
public Shader(string VertexShaderSource, string FragmentShaderSource, bool VertextBuiltIn = false, bool FragmentShaderBuiltIn = false, Assembly? Assembly = null)
|
||||||
|
{
|
||||||
|
VertexShader = GL.CreateShader(ShaderType.VertexShader);
|
||||||
|
string Base = "GraphicsManager.Resources.Shaders.";
|
||||||
|
if (Assembly is not null) Base = string.Empty;
|
||||||
|
string vss = (VertextBuiltIn ? Tools.GetResourceString((Assembly == null ? typeof(Tools).Assembly : Assembly), $"{Base}{VertexShaderSource}") : File.ReadAllText(VertexShaderSource))!;
|
||||||
|
string fss = (FragmentShaderBuiltIn ? Tools.GetResourceString((Assembly ?? typeof(Tools).Assembly), $"{Base}{FragmentShaderSource}") : File.ReadAllText(FragmentShaderSource))!;
|
||||||
|
GL.ShaderSource(VertexShader, vss);
|
||||||
|
|
||||||
|
FragmentShader = GL.CreateShader(ShaderType.FragmentShader);
|
||||||
|
GL.ShaderSource(FragmentShader, fss);
|
||||||
|
|
||||||
|
GL.CompileShader(VertexShader);
|
||||||
|
|
||||||
|
string infoLogVert = GL.GetShaderInfoLog(VertexShader);
|
||||||
|
if (infoLogVert != string.Empty)
|
||||||
|
Console.WriteLine(infoLogVert);
|
||||||
|
|
||||||
|
GL.CompileShader(FragmentShader);
|
||||||
|
|
||||||
|
string infoLogFrag = GL.GetShaderInfoLog(FragmentShader);
|
||||||
|
|
||||||
|
if (infoLogFrag != string.Empty)
|
||||||
|
Console.WriteLine(infoLogFrag);
|
||||||
|
|
||||||
|
Handle = GL.CreateProgram();
|
||||||
|
|
||||||
|
GL.AttachShader(Handle, VertexShader);
|
||||||
|
GL.AttachShader(Handle, FragmentShader);
|
||||||
|
|
||||||
|
GL.LinkProgram(Handle);
|
||||||
|
|
||||||
|
GL.DetachShader(Handle, VertexShader);
|
||||||
|
GL.DetachShader(Handle, FragmentShader);
|
||||||
|
GL.DeleteShader(FragmentShader);
|
||||||
|
GL.DeleteShader(VertexShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shader(string ShaderSource, bool Embeded = false, Assembly? Assembly = null)
|
||||||
|
{
|
||||||
|
VertexShader = GL.CreateShader(ShaderType.VertexShader);
|
||||||
|
string Base = "GraphicsManager.Resources.Shaders.";
|
||||||
|
if (Assembly is not null) Base = string.Empty;
|
||||||
|
GL.ShaderSource(VertexShader, (Embeded ? Tools.GetResourceString((Assembly ?? typeof(Tools).Assembly), $"{Base}{ShaderSource}.vert") : File.ReadAllText($"{ShaderSource}.vert")));
|
||||||
|
|
||||||
|
FragmentShader = GL.CreateShader(ShaderType.FragmentShader);
|
||||||
|
GL.ShaderSource(FragmentShader, (Embeded ? Tools.GetResourceString((Assembly ?? typeof(Tools).Assembly), $"{Base}{ShaderSource}.frag") : File.ReadAllText($"{ShaderSource}.frag")));
|
||||||
|
|
||||||
|
GL.CompileShader(VertexShader);
|
||||||
|
|
||||||
|
string infoLogVert = GL.GetShaderInfoLog(VertexShader);
|
||||||
|
if (infoLogVert != string.Empty)
|
||||||
|
Console.WriteLine(infoLogVert);
|
||||||
|
|
||||||
|
GL.CompileShader(FragmentShader);
|
||||||
|
|
||||||
|
string infoLogFrag = GL.GetShaderInfoLog(FragmentShader);
|
||||||
|
|
||||||
|
if (infoLogFrag != string.Empty)
|
||||||
|
Console.WriteLine(infoLogFrag);
|
||||||
|
|
||||||
|
Handle = GL.CreateProgram();
|
||||||
|
|
||||||
|
GL.AttachShader(Handle, VertexShader);
|
||||||
|
GL.AttachShader(Handle, FragmentShader);
|
||||||
|
|
||||||
|
GL.LinkProgram(Handle);
|
||||||
|
|
||||||
|
GL.DetachShader(Handle, VertexShader);
|
||||||
|
GL.DetachShader(Handle, FragmentShader);
|
||||||
|
GL.DeleteShader(FragmentShader);
|
||||||
|
GL.DeleteShader(VertexShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Use()
|
||||||
|
{
|
||||||
|
GL.UseProgram(Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetAttribLocation(string attribName)
|
||||||
|
{
|
||||||
|
return GL.GetAttribLocation(Handle, attribName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetInt(string name, int value)
|
||||||
|
{
|
||||||
|
int location = GL.GetUniformLocation(Handle, name);
|
||||||
|
|
||||||
|
GL.Uniform1(location, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shader Clone()
|
||||||
|
{
|
||||||
|
return (Shader)MemberwiseClone();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!disposedValue)
|
||||||
|
{
|
||||||
|
GL.DeleteProgram(Handle);
|
||||||
|
|
||||||
|
disposedValue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Shader()
|
||||||
|
{
|
||||||
|
GL.DeleteProgram(Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
106
GraphicsManager/Objects/Core/Texture.cs
Normal file
106
GraphicsManager/Objects/Core/Texture.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
using GraphicsManager.Structs;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using SharpFont;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using Image = SixLabors.ImageSharp.Image;
|
||||||
|
|
||||||
|
namespace GraphicsManager.Objects.Core;
|
||||||
|
|
||||||
|
public class Texture
|
||||||
|
{
|
||||||
|
public static readonly Shader TextureShader = new("RectangleTexture", true);
|
||||||
|
|
||||||
|
public int handel;
|
||||||
|
public Texture(byte[] File)
|
||||||
|
{
|
||||||
|
Image<Rgba32> image = Image.Load<Rgba32>(File);
|
||||||
|
image.Mutate(x => x.Flip(FlipMode.Vertical));
|
||||||
|
|
||||||
|
var pixels = new List<byte>(4 * image.Width * image.Height);
|
||||||
|
|
||||||
|
for (int y = 0; y < image.Height; y++)
|
||||||
|
{
|
||||||
|
var row = image.GetPixelRowSpan(y);
|
||||||
|
|
||||||
|
for (int x = 0; x < image.Width; x++)
|
||||||
|
{
|
||||||
|
pixels.Add(row[x].R);
|
||||||
|
pixels.Add(row[x].G);
|
||||||
|
pixels.Add(row[x].B);
|
||||||
|
pixels.Add(row[x].A);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handel = GL.GenTexture();
|
||||||
|
GL.BindTexture(TextureTarget.Texture2D, handel);
|
||||||
|
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels.ToArray());
|
||||||
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
||||||
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Texture(Label l, char charter, uint PixelHeight, Face face)
|
||||||
|
{
|
||||||
|
if (!Label._characters.ContainsKey(l)) Label._characters.Add(l, new Dictionary<uint, Character>());
|
||||||
|
face.SetPixelSizes(0, PixelHeight);
|
||||||
|
|
||||||
|
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
|
||||||
|
|
||||||
|
GL.ActiveTexture(TextureUnit.Texture0);
|
||||||
|
face.SelectCharmap(Encoding.Unicode);
|
||||||
|
ushort temp = ((ushort)charter);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
face.LoadChar(temp, LoadFlags.Render, LoadTarget.Normal);
|
||||||
|
GlyphSlot glyph = face.Glyph;
|
||||||
|
FTBitmap bitmap = glyph.Bitmap;
|
||||||
|
|
||||||
|
handel = GL.GenTexture();
|
||||||
|
GL.BindTexture(TextureTarget.Texture2D, handel);
|
||||||
|
GL.TexImage2D(TextureTarget.Texture2D, 0,
|
||||||
|
PixelInternalFormat.R8, bitmap.Width, bitmap.Rows, 0,
|
||||||
|
PixelFormat.Red, PixelType.UnsignedByte, bitmap.Buffer);
|
||||||
|
|
||||||
|
|
||||||
|
Character cha = new()
|
||||||
|
{
|
||||||
|
Size = new Vector2(bitmap.Width, bitmap.Rows),
|
||||||
|
Bearing = new Vector2(glyph.BitmapLeft, glyph.BitmapTop),
|
||||||
|
Advance = (int)glyph.Advance.X.Value,
|
||||||
|
Texture = this,
|
||||||
|
};
|
||||||
|
|
||||||
|
Label._characters[l].Add(temp, cha);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadText()
|
||||||
|
{
|
||||||
|
GL.TextureParameter(handel, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
||||||
|
GL.TextureParameter(handel, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
||||||
|
GL.TextureParameter(handel, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
|
||||||
|
GL.TextureParameter(handel, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load(int loc)
|
||||||
|
{
|
||||||
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
|
||||||
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
|
||||||
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
|
||||||
|
GL.EnableVertexAttribArray(loc);
|
||||||
|
GL.VertexAttribPointer(loc, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Use(TextureUnit unit = TextureUnit.Texture0)
|
||||||
|
{
|
||||||
|
GL.ActiveTexture(unit);
|
||||||
|
GL.BindTexture(TextureTarget.Texture2D, handel);
|
||||||
|
}
|
||||||
|
}
|
214
GraphicsManager/Objects/Label.cs
Normal file
214
GraphicsManager/Objects/Label.cs
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using GraphicsManager.Structs;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using SharpFont;
|
||||||
|
using System.Reflection;
|
||||||
|
using Encoding = SharpFont.Encoding;
|
||||||
|
|
||||||
|
namespace GraphicsManager.Objects;
|
||||||
|
|
||||||
|
public class Label : IRenderObject
|
||||||
|
{
|
||||||
|
public static readonly Shader DefaultTextShader = new("Label", true);
|
||||||
|
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; } }
|
||||||
|
public bool Visible { get; set; } = true;
|
||||||
|
|
||||||
|
public static readonly Dictionary<Label, Dictionary<uint, Character>> _characters = new();
|
||||||
|
private string text = string.Empty;
|
||||||
|
public int VAO { get; set; }
|
||||||
|
public int VBO { get; set; }
|
||||||
|
public Vector2 DIR { get; set; } = new Vector2(1f, 0f);
|
||||||
|
public string Text
|
||||||
|
{
|
||||||
|
get => text;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Loaded)
|
||||||
|
{
|
||||||
|
Library lib = new();
|
||||||
|
Face face = new(lib, Font.GetData(), 0);
|
||||||
|
|
||||||
|
face.SetPixelSizes(0, PixelHeight);
|
||||||
|
|
||||||
|
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
|
||||||
|
|
||||||
|
face.SelectCharmap(Encoding.Unicode);
|
||||||
|
if (!_characters.ContainsKey(this)) _characters.Add(this, new Dictionary<uint, Character>());
|
||||||
|
foreach (char character in value)
|
||||||
|
{
|
||||||
|
if (_characters[this].ContainsKey(character) == false)
|
||||||
|
{
|
||||||
|
var f = new Texture(this, character, PixelHeight, face);
|
||||||
|
f.LoadText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public uint PixelHeight { get; set; } = 20;
|
||||||
|
public float Scale { get; set; } = 1.2f;
|
||||||
|
public Shader Shader { get; } = DefaultTextShader;
|
||||||
|
public Font Font { get; set; } = Font.MakeEmbeddedFont("TektonPro-Regular.otf");
|
||||||
|
|
||||||
|
public Vector4 Color { get; set; } = new Vector4(1, 1, 1, 1);
|
||||||
|
public Vector2i Distance { get; private set; }
|
||||||
|
private Vector2i loc_ = new();
|
||||||
|
private Vector2i locc_ = new();
|
||||||
|
public Vector2i Location
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return loc_;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
|
||||||
|
loc_ = value;
|
||||||
|
if (Window is null || Parent is null) return;
|
||||||
|
locc_ = new(value.X + Parent.Position.X, value.Y + Parent.Position.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Vector2i Size { get; set; }
|
||||||
|
|
||||||
|
public void Clean()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
if (Visible & loadd)
|
||||||
|
{
|
||||||
|
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(locc_.X, locc_.Y, 0f));
|
||||||
|
|
||||||
|
float char_x = 0.0f;
|
||||||
|
|
||||||
|
Library lib = new();
|
||||||
|
|
||||||
|
Face face = new(lib, Font.GetData(), 0);
|
||||||
|
|
||||||
|
face.SetPixelSizes(0, PixelHeight);
|
||||||
|
|
||||||
|
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
|
||||||
|
|
||||||
|
GL.ActiveTexture(TextureUnit.Texture0);
|
||||||
|
face.SelectCharmap(Encoding.Unicode);
|
||||||
|
|
||||||
|
|
||||||
|
float hhh = 0f;
|
||||||
|
foreach (char c in Text)
|
||||||
|
{
|
||||||
|
if (!_characters[this].ContainsKey(c)) break;
|
||||||
|
Character ch = _characters[this][c];
|
||||||
|
|
||||||
|
if (c == '\n')
|
||||||
|
{
|
||||||
|
hhh += PixelHeight;
|
||||||
|
char_x = 0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GL.Disable(EnableCap.Blend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Window? Window { get; private set; }
|
||||||
|
|
||||||
|
public void LoadToParent(IParent window, Window win)
|
||||||
|
{
|
||||||
|
Parent = window;
|
||||||
|
Window = win;
|
||||||
|
//X = window.FloatToInt(X, window.Size.X);
|
||||||
|
//Y = window.FloatToInt(Y, window.Size.Y, true);
|
||||||
|
Library lib = new();
|
||||||
|
|
||||||
|
Face face = new(lib, Font.GetData(), 0);
|
||||||
|
face.SetPixelSizes(0, PixelHeight);
|
||||||
|
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
|
||||||
|
face.SelectCharmap(Encoding.Unicode);
|
||||||
|
|
||||||
|
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
VBO = GL.GenBuffer();
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, VBO);
|
||||||
|
GL.BufferData(BufferTarget.ArrayBuffer, 4 * 6 * 4, vquad, BufferUsageHint.StaticDraw);
|
||||||
|
|
||||||
|
VAO = GL.GenVertexArray();
|
||||||
|
if (!_characters.ContainsKey(this)) _characters.Add(this, new Dictionary<uint, Character>());
|
||||||
|
foreach (char character in Text)
|
||||||
|
{
|
||||||
|
if (_characters[this].ContainsKey(character) == false)
|
||||||
|
{
|
||||||
|
var f = new Texture(this, character, PixelHeight, face);
|
||||||
|
f.LoadText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
Text = text;
|
||||||
|
loadd = true;
|
||||||
|
Location = Location;
|
||||||
|
Distance = new(window.Size.X - Size.X - Location.X, window.Size.Y - Size.Y - Location.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool loadd = false;
|
||||||
|
|
||||||
|
public event Func<IRenderObject, Task>? Clicked;
|
||||||
|
|
||||||
|
public bool Loaded => loadd;
|
||||||
|
}
|
212
GraphicsManager/Objects/Rectangle.cs
Normal file
212
GraphicsManager/Objects/Rectangle.cs
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace GraphicsManager.Objects;
|
||||||
|
|
||||||
|
public class Rectangle : ITextureObject
|
||||||
|
{
|
||||||
|
public static readonly Shader DefaultShader = new("Rectangle", true);
|
||||||
|
|
||||||
|
public ObjectAnchor Anchor { get; set; } = ObjectAnchor.Left | ObjectAnchor.Top;
|
||||||
|
|
||||||
|
public Texture? Texture { get; private set; }
|
||||||
|
|
||||||
|
public Rectangle(Texture? texture = null)
|
||||||
|
{
|
||||||
|
Texture = texture;
|
||||||
|
if (Points_ is null)
|
||||||
|
{
|
||||||
|
bool tex = (Texture is null);
|
||||||
|
Points_ = new float[(tex ? 12 : 20)];
|
||||||
|
if (!tex)
|
||||||
|
{
|
||||||
|
Points[3] = 1.0f;
|
||||||
|
Points[4] = 1.0f;
|
||||||
|
Points[8] = 1.0f;
|
||||||
|
Points[19] = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector4 Color { get; set; }
|
||||||
|
|
||||||
|
public bool Visible { get; set; } = true;
|
||||||
|
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
if (Visible)
|
||||||
|
{
|
||||||
|
if (Texture is not null) Texture.Use();
|
||||||
|
Shader.Use();
|
||||||
|
GL.Uniform4(0, Color);
|
||||||
|
if (Texture is not null)
|
||||||
|
{
|
||||||
|
GL.Enable(EnableCap.Blend);
|
||||||
|
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
||||||
|
GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
|
||||||
|
}
|
||||||
|
GL.BindVertexArray(ArrayObject);
|
||||||
|
GL.DrawElements(PrimitiveType.Triangles, Indexs.Length, DrawElementsType.UnsignedInt, 0);
|
||||||
|
if (Texture is not null) GL.Disable(EnableCap.Blend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clean()
|
||||||
|
{
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
||||||
|
GL.DeleteBuffer(BufferObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadToParent(IParent Parent, Window Window)
|
||||||
|
{
|
||||||
|
this.Parent = Parent;
|
||||||
|
this.Window = Window;
|
||||||
|
int pos = Points.Length - 3;
|
||||||
|
if (Texture is not null) pos -= 2;
|
||||||
|
pos = 4;
|
||||||
|
if (Texture is not null) pos += 2;
|
||||||
|
|
||||||
|
BufferObject = GL.GenBuffer();
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, BufferObject);
|
||||||
|
ArrayObject = GL.GenVertexArray();
|
||||||
|
GL.BindVertexArray(ArrayObject);
|
||||||
|
int add = 3;
|
||||||
|
if (Texture is not null) add = 5;
|
||||||
|
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, add * sizeof(float), 0);
|
||||||
|
if (Texture is not null)
|
||||||
|
{
|
||||||
|
Shader = Texture.TextureShader;
|
||||||
|
Texture.Load(Shader.GetAttribLocation("aTexCoord"));
|
||||||
|
}
|
||||||
|
GL.EnableVertexAttribArray(0);
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, BufferObject);
|
||||||
|
GL.BufferData(BufferTarget.ArrayBuffer, Points.Length * sizeof(float), Points, Hint);
|
||||||
|
GL.BindVertexArray(ArrayObject);
|
||||||
|
ElementBufferObject = GL.GenBuffer();
|
||||||
|
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ElementBufferObject);
|
||||||
|
GL.BufferData(BufferTarget.ElementArrayBuffer, Indexs.Length * sizeof(uint), Indexs, Hint);
|
||||||
|
load = true;
|
||||||
|
loadd = true;
|
||||||
|
|
||||||
|
Window.MouseDown += Window_MouseDown;
|
||||||
|
Location = Location;
|
||||||
|
Distance = new(Parent.Size.X - Size.X - Location.X, Parent.Size.Y - Size.Y - Location.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IParent? Parent { get; private set; }
|
||||||
|
public Window? Window { get; private set; }
|
||||||
|
|
||||||
|
private void Window_MouseDown(OpenTK.Windowing.Common.MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
if (Clicked is not null && e.Button == OpenTK.Windowing.GraphicsLibraryFramework.MouseButton.Button1 && Location.X <= Parent?.MousePosition.X && Size.X + Location.X >= Parent?.MousePosition.X && Location.Y + Size.Y >= Parent?.MousePosition.Y && Location.Y <= Parent?.MousePosition.Y) Clicked.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Rectangle()
|
||||||
|
{
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
||||||
|
GL.DeleteBuffer(BufferObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shader Shader { get; set; } = DefaultShader;
|
||||||
|
public int ElementBufferObject { get; private set; }
|
||||||
|
public int BufferObject { get; private set; }
|
||||||
|
public int ArrayObject { get; private set; }
|
||||||
|
private float[] Points_;
|
||||||
|
private Vector2i size_ = new(), loc_ = new();
|
||||||
|
bool load = false;
|
||||||
|
|
||||||
|
public float[] Points
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Points_;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Points_ = value;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (load)
|
||||||
|
{
|
||||||
|
int add = 3;
|
||||||
|
if (Texture is not null) add = 5;
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, BufferObject);
|
||||||
|
GL.BindVertexArray(ArrayObject);
|
||||||
|
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, add * sizeof(float), 0);
|
||||||
|
GL.EnableVertexAttribArray(0);
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, BufferObject);
|
||||||
|
GL.BufferData(BufferTarget.ArrayBuffer, Points_.Length * sizeof(float), Points_, Hint);
|
||||||
|
GL.BindVertexArray(ArrayObject);
|
||||||
|
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ElementBufferObject);
|
||||||
|
GL.BufferData(BufferTarget.ElementArrayBuffer, Indexs.Length * sizeof(uint), Indexs, Hint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (AccessViolationException v)
|
||||||
|
{
|
||||||
|
Console.WriteLine(v.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint[] Indexs { get; set; } = new uint[6] { 0, 1, 3, 1, 2, 3 };
|
||||||
|
public BufferUsageHint Hint { get; set; } = BufferUsageHint.StaticDraw;
|
||||||
|
|
||||||
|
private bool loadd = false;
|
||||||
|
|
||||||
|
public event Func<IRenderObject, Task>? Clicked;
|
||||||
|
|
||||||
|
public bool Loaded => loadd;
|
||||||
|
public Vector2i Distance { get; private set; }
|
||||||
|
|
||||||
|
public Vector2i Size
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return size_;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
size_ = value;
|
||||||
|
if (Window is null || Parent is null) return;
|
||||||
|
float[] temp = Points;
|
||||||
|
saf = new Vector2(Window.IntToFloat(value.X + loc_.X + Parent.Position.X, false), Window.IntToFloat(value.Y + loc_.Y + Parent.Position.Y, true));
|
||||||
|
temp[0] = saf.X;
|
||||||
|
temp[(Texture is null ? 3 : 5)] = saf.X;
|
||||||
|
temp[(Texture is null ? 4 : 6)] = saf.Y;
|
||||||
|
temp[(Texture is null ? 7 : 11)] = saf.Y;
|
||||||
|
Points = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2i Location
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return loc_;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
loc_ = value;
|
||||||
|
if (Window is null || Parent is null) return;
|
||||||
|
float[] temp = Points;
|
||||||
|
laf = new Vector2(Window.IntToFloat(value.X + Parent.Position.X, false), Window.IntToFloat(value.Y + Parent.Position.Y, true));
|
||||||
|
temp[(Texture is null ? 6 : 10)] = laf.X;
|
||||||
|
temp[(Texture is null ? 9 : 15)] = laf.X;
|
||||||
|
temp[1] = laf.Y;
|
||||||
|
temp[(Texture is null ? 10 : 16)] = laf.Y;
|
||||||
|
saf = new Vector2(Window.IntToFloat(Size.X + value.X + Parent.Position.X, false), Window.IntToFloat(Size.Y + value.Y + Parent.Position.Y, true));
|
||||||
|
temp[0] = saf.X;
|
||||||
|
temp[(Texture is null ? 3 : 5)] = saf.X;
|
||||||
|
temp[(Texture is null ? 4 : 6)] = saf.Y;
|
||||||
|
temp[(Texture is null ? 7 : 11)] = saf.Y;
|
||||||
|
Points = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Vector2 laf = new(), saf = new();
|
||||||
|
|
||||||
|
public Vector2 LocationAsFloat { get { return laf; } }
|
||||||
|
public Vector2 SizeAsFloat { get { return saf; } }
|
||||||
|
}
|
121
GraphicsManager/Objects/Textbox.cs
Normal file
121
GraphicsManager/Objects/Textbox.cs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||||
|
|
||||||
|
namespace GraphicsManager.Objects;
|
||||||
|
|
||||||
|
public class Textbox : ITextureObject
|
||||||
|
{
|
||||||
|
public event Func<IRenderObject, Task>? Clicked;
|
||||||
|
public Rectangle Bounds;
|
||||||
|
public Label Label;
|
||||||
|
public IParent Parent { get; private set; }
|
||||||
|
public Textbox(Texture texture = null!)
|
||||||
|
{
|
||||||
|
Bounds = new Rectangle(texture ?? new Texture(Tools.GetResourceBytes("GraphicsManager.Resources.Textures.Textbox.png")));
|
||||||
|
Label = new Label()
|
||||||
|
{
|
||||||
|
Text = nameof(Textbox)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public Vector2i Size { get { return Bounds.Size; } set { Bounds.Size = value; } }
|
||||||
|
public Vector2i Location { get { return Bounds.Location; } set { Bounds.Location = value; } }
|
||||||
|
public Vector2i Distance { get { return Bounds.Distance; }}
|
||||||
|
public Texture Texture => Bounds.Texture!;
|
||||||
|
|
||||||
|
public string Text { get => Label.Text; set => Label.Text = value; }
|
||||||
|
public Font Font { get => Label.Font; set => Label.Font = value; }
|
||||||
|
public Vector4 BackgroundColor { get => Bounds.Color; set => Bounds.Color = value; }
|
||||||
|
public float[] Points
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Bounds.Points;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Label is not null && Parent is not null)
|
||||||
|
{
|
||||||
|
Label.Location = new Vector2i((int)Parent.FloatToInt(value[10] + ((-1 - Parent.IntToFloat(10)) * -1)), (int)Parent.FloatToInt(value[6] + (-1 - Parent.IntToFloat(5)) * -1, true));
|
||||||
|
}
|
||||||
|
Bounds.Points = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectAnchor Anchor { get; set; } = ObjectAnchor.Left | ObjectAnchor.Top;
|
||||||
|
|
||||||
|
private bool _loaded = false;
|
||||||
|
public bool Loaded => _loaded;
|
||||||
|
|
||||||
|
public bool Visible { get; set; } = true;
|
||||||
|
|
||||||
|
public void Clean()
|
||||||
|
{
|
||||||
|
Bounds.Clean();
|
||||||
|
Label.Clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
Bounds.Draw();
|
||||||
|
Label.Draw();
|
||||||
|
}
|
||||||
|
public Window? Window { get; private set; }
|
||||||
|
public void LoadToParent(IParent Parent, Window Window)
|
||||||
|
{
|
||||||
|
this.Parent = Parent;
|
||||||
|
this.Window = Window;
|
||||||
|
this.Parent.MouseDown += Parrent_MouseDown;
|
||||||
|
this.Parent.KeyDown += Parrent_KeyDown;
|
||||||
|
Bounds.LoadToParent(Parent, Window);
|
||||||
|
Points = Points;
|
||||||
|
Label.LoadToParent(Parent, Window);
|
||||||
|
_loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Parrent_KeyDown(OpenTK.Windowing.Common.KeyboardKeyEventArgs obj)
|
||||||
|
{
|
||||||
|
if (use)
|
||||||
|
{
|
||||||
|
if (obj.Key == Keys.CapsLock || obj.Key == Keys.Menu || obj.Key == Keys.LeftSuper || obj.Key == Keys.RightSuper || obj.Key == Keys.End || obj.Key == Keys.Home || obj.Key == Keys.PageDown || obj.Key == Keys.PageUp || obj.Key == Keys.Insert || obj.Key == Keys.Up || obj.Key == Keys.Down || obj.Key == Keys.Left || obj.Key == Keys.Right) return;
|
||||||
|
if (obj.Key == Keys.Backspace)
|
||||||
|
{
|
||||||
|
if (!(Text.Length > 0)) return;
|
||||||
|
Text = Text.Remove(Text.Length - 1, 1);
|
||||||
|
}
|
||||||
|
else if (obj.Key == Keys.Delete)
|
||||||
|
{
|
||||||
|
if (!(Text.Length > 0)) return;
|
||||||
|
Text = Text.Remove(Text.Length - 1, 1);
|
||||||
|
}
|
||||||
|
else if (obj.Shift)
|
||||||
|
{
|
||||||
|
if (obj.Key == Keys.Enter || obj.Key == Keys.KeyPadEnter) Text += '\n';
|
||||||
|
else if (obj.Key == Keys.LeftShift || obj.Key == Keys.KeyPadEnter || obj.Key == Keys.Enter || obj.Key == Keys.End || obj.Key == Keys.Down) return;
|
||||||
|
else Text += ((char)obj.Key).ToString().ToUpper();
|
||||||
|
}
|
||||||
|
else if (obj.Command || obj.Alt || obj.Control) { }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Text += ((char)obj.Key).ToString().ToLower();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool use = false;
|
||||||
|
|
||||||
|
private void Parrent_MouseDown(OpenTK.Windowing.Common.MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Button == MouseButton.Button1 && Location.X <= Parent?.MousePosition.X && Size.X + Location.X >= Parent?.MousePosition.X && Location.Y + Size.Y >= Parent?.MousePosition.Y && Location.Y <= Parent?.MousePosition.Y)
|
||||||
|
{
|
||||||
|
use = true;
|
||||||
|
if (Clicked is not null) Clicked.Invoke(this);
|
||||||
|
}
|
||||||
|
else use = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 LocationAsFloat { get { return Bounds.LocationAsFloat; } }
|
||||||
|
public Vector2 SizeAsFloat { get { return Bounds.SizeAsFloat; } }
|
||||||
|
}
|
183
GraphicsManager/Objects/UserControl.cs
Normal file
183
GraphicsManager/Objects/UserControl.cs
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Common;
|
||||||
|
|
||||||
|
namespace GraphicsManager.Objects;
|
||||||
|
|
||||||
|
public class UserControl : IRenderObject, IParent
|
||||||
|
{
|
||||||
|
private Rectangle _bounds;
|
||||||
|
|
||||||
|
public UserControl()
|
||||||
|
{
|
||||||
|
_bounds = new Rectangle();
|
||||||
|
_bounds.Clicked += _bounds_Clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task _bounds_Clicked(IRenderObject arg)
|
||||||
|
{
|
||||||
|
_ = Clicked?.Invoke(arg)!;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICollection<IRenderObject> Controls { get; } = new List<IRenderObject>();
|
||||||
|
public ObjectAnchor Anchor { get => _bounds.Anchor; set => _bounds.Anchor = value; }
|
||||||
|
public Vector4 Color { get => _bounds.Color; set => _bounds.Color = value; }
|
||||||
|
public bool Visible { get => _bounds.Visible; set => _bounds.Visible = value; }
|
||||||
|
public Vector2i Size { get => _bounds.Size; set => _bounds.Size = value; }
|
||||||
|
public Vector2 SizeAsFloat { get => _bounds.SizeAsFloat; }
|
||||||
|
public Vector2i Location { get => _bounds.Location; set => _bounds.Location = value; }
|
||||||
|
public Vector2i Position => Location;
|
||||||
|
public Vector2 LocationAsFloat { get => _bounds.LocationAsFloat; }
|
||||||
|
public Vector2i Distance { get => _bounds.Distance; }
|
||||||
|
public event Func<IRenderObject, Task>? Clicked;
|
||||||
|
public event Action<MouseButtonEventArgs> MouseDown;
|
||||||
|
public event Action<KeyboardKeyEventArgs> KeyDown;
|
||||||
|
|
||||||
|
public IParent? Parent { get; private set; }
|
||||||
|
public Window? Window { get; private set; }
|
||||||
|
public bool Loaded { get; private set; } = false;
|
||||||
|
|
||||||
|
public Vector2 MousePosition => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public void LoadToParent(IParent Parent, Window Window)
|
||||||
|
{
|
||||||
|
this.Parent = Parent;
|
||||||
|
this.Window = Window;
|
||||||
|
_bounds.LoadToParent(Parent, Window);
|
||||||
|
foreach (IRenderObject obj in Controls)
|
||||||
|
{
|
||||||
|
obj.LoadToParent(this, Window);
|
||||||
|
}
|
||||||
|
Loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
if (Loaded)
|
||||||
|
{
|
||||||
|
_bounds.Draw();
|
||||||
|
IEnumerable<IRenderObject> needload = Controls.Where(a => a.Loaded == false);
|
||||||
|
|
||||||
|
if (needload.Any())
|
||||||
|
{
|
||||||
|
foreach (IRenderObject Control in needload)
|
||||||
|
{
|
||||||
|
Control.LoadToParent(this, Window!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (IRenderObject Control in Controls)
|
||||||
|
{
|
||||||
|
Control.Draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clean()
|
||||||
|
{
|
||||||
|
foreach (IRenderObject Control in Controls)
|
||||||
|
{
|
||||||
|
Control.Clean();
|
||||||
|
}
|
||||||
|
_bounds.Clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Resize(ResizeEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Width == 0 && e.Height == 0) return;
|
||||||
|
foreach (IRenderObject Control in Controls)
|
||||||
|
{
|
||||||
|
if (Control.Loaded)
|
||||||
|
{
|
||||||
|
bool top = (Control.Anchor & ObjectAnchor.Top) == ObjectAnchor.Top;
|
||||||
|
bool left = (Control.Anchor & ObjectAnchor.Left) == ObjectAnchor.Left;
|
||||||
|
bool right = (Control.Anchor & ObjectAnchor.Right) == ObjectAnchor.Right;
|
||||||
|
bool bottom = (Control.Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom;
|
||||||
|
if (!top && !bottom) { Control.Anchor |= ObjectAnchor.Top; top = true; }
|
||||||
|
if (!left && !right) { Control.Anchor |= ObjectAnchor.Left; left = true; }
|
||||||
|
int lx = (left ? Control.Location.X : Size.X - Control.Distance.X - Control.Size.X);
|
||||||
|
int ly = (top ? Control.Location.Y : Size.Y - Control.Distance.Y - Control.Size.Y);
|
||||||
|
int sy = (bottom ? Size.Y - Control.Distance.Y - ly : Control.Size.Y);
|
||||||
|
int sx = (right ? Size.X - Control.Distance.X - lx : Control.Size.X);
|
||||||
|
Control.Size = new(sx, sy);
|
||||||
|
Control.Location = new(lx, ly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#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 float IntToFloat(int p, bool Invert = false)
|
||||||
|
{
|
||||||
|
int 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)
|
||||||
|
{
|
||||||
|
int 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
|
||||||
|
}
|
BIN
GraphicsManager/Resources/Fonts/TektonPro-Regular.otf
Normal file
BIN
GraphicsManager/Resources/Fonts/TektonPro-Regular.otf
Normal file
Binary file not shown.
16
GraphicsManager/Resources/Shaders/Label.frag
Normal file
16
GraphicsManager/Resources/Shaders/Label.frag
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
in vec2 vUV;
|
||||||
|
|
||||||
|
layout (binding=0) uniform sampler2D u_texture;
|
||||||
|
|
||||||
|
layout (location = 2) uniform vec4 textColor;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 uv = vUV.xy;
|
||||||
|
float text = texture(u_texture, uv).r;
|
||||||
|
fragColor = vec4(textColor.rgba*text);
|
||||||
|
}
|
15
GraphicsManager/Resources/Shaders/Label.vert
Normal file
15
GraphicsManager/Resources/Shaders/Label.vert
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 in_pos;
|
||||||
|
layout (location = 1) in vec2 in_uv;
|
||||||
|
|
||||||
|
out vec2 vUV;
|
||||||
|
|
||||||
|
layout (location = 0) uniform mat4 model;
|
||||||
|
layout (location = 1) uniform mat4 projection;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vUV = in_uv.xy;
|
||||||
|
gl_Position = projection * model * vec4(in_pos.xy, 0.0, 1.0);
|
||||||
|
}
|
9
GraphicsManager/Resources/Shaders/Rectangle.frag
Normal file
9
GraphicsManager/Resources/Shaders/Rectangle.frag
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#version 330 core
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in vec4 vertexColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = vertexColor;
|
||||||
|
}
|
10
GraphicsManager/Resources/Shaders/Rectangle.vert
Normal file
10
GraphicsManager/Resources/Shaders/Rectangle.vert
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
uniform vec4 objColor;
|
||||||
|
out vec4 vertexColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(aPos, 1.0);
|
||||||
|
vertexColor = objColor;
|
||||||
|
}
|
8
GraphicsManager/Resources/Shaders/RectangleTexture.frag
Normal file
8
GraphicsManager/Resources/Shaders/RectangleTexture.frag
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#version 330
|
||||||
|
out vec4 outputColor;
|
||||||
|
in vec2 texCoord;
|
||||||
|
uniform sampler2D texture1;
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
outputColor = texture(texture1, texCoord);
|
||||||
|
}
|
9
GraphicsManager/Resources/Shaders/RectangleTexture.vert
Normal file
9
GraphicsManager/Resources/Shaders/RectangleTexture.vert
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#version 330
|
||||||
|
layout(location = 0) in vec3 aPosition;
|
||||||
|
layout(location = 1) in vec2 aTexCoord;
|
||||||
|
out vec2 texCoord;
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
texCoord = aTexCoord;
|
||||||
|
gl_Position = vec4(aPosition, 1.0);
|
||||||
|
}
|
BIN
GraphicsManager/Resources/Textures/Textbox.png
Normal file
BIN
GraphicsManager/Resources/Textures/Textbox.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 267 B |
12
GraphicsManager/Structs/Character.cs
Normal file
12
GraphicsManager/Structs/Character.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using GraphicsManager.Objects.Core;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
|
namespace GraphicsManager.Structs;
|
||||||
|
|
||||||
|
public struct Character
|
||||||
|
{
|
||||||
|
public Texture Texture { get; set; }
|
||||||
|
public Vector2 Size { get; set; }
|
||||||
|
public Vector2 Bearing { get; set; }
|
||||||
|
public int Advance { get; set; }
|
||||||
|
}
|
31
GraphicsManager/Tools.cs
Normal file
31
GraphicsManager/Tools.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace GraphicsManager;
|
||||||
|
|
||||||
|
public class Tools
|
||||||
|
{
|
||||||
|
public static byte[] GetResourceBytes(Assembly Assembly, string Resource)
|
||||||
|
{
|
||||||
|
Stream str = Assembly.GetManifestResourceStream(Resource)!;
|
||||||
|
MemoryStream ms = new();
|
||||||
|
str.CopyTo(ms);
|
||||||
|
str.Dispose();
|
||||||
|
byte[] result = ms.ToArray();
|
||||||
|
ms.Dispose();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetResourceString(Assembly Assembly, string Resource)
|
||||||
|
{
|
||||||
|
Stream str = Assembly.GetManifestResourceStream(Resource)!;
|
||||||
|
StreamReader sr = new(str);
|
||||||
|
string result = sr.ReadToEnd();
|
||||||
|
sr.Dispose();
|
||||||
|
str.Dispose();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] GetResourceBytes(string Resource) => GetResourceBytes(typeof(Tools).Assembly, Resource);
|
||||||
|
|
||||||
|
public static string GetResourceString(string Resource) => GetResourceString(typeof(Tools).Assembly, Resource);
|
||||||
|
}
|
165
GraphicsManager/Window.cs
Normal file
165
GraphicsManager/Window.cs
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
using GraphicsManager.Enums;
|
||||||
|
using GraphicsManager.Interfaces;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Common;
|
||||||
|
using OpenTK.Windowing.Desktop;
|
||||||
|
|
||||||
|
namespace GraphicsManager;
|
||||||
|
|
||||||
|
public class Window : NativeWindow , IParent
|
||||||
|
{
|
||||||
|
public Window(NativeWindowSettings nativeWindowSettings) : base(nativeWindowSettings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Window() : base(new NativeWindowSettings())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public Vector2i Position { get; } = new Vector2i(0, 0);
|
||||||
|
public Color4 BackgroundColor { get; set; } = new Color4(0, 0, 0, 255);
|
||||||
|
|
||||||
|
public ICollection<IRenderObject> Controls { get; } = new List<IRenderObject>();
|
||||||
|
#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 float IntToFloat(int p, bool Invert = false)
|
||||||
|
{
|
||||||
|
int 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)
|
||||||
|
{
|
||||||
|
int 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 void Resize(ResizeEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Width == 0 && e.Height == 0) return;
|
||||||
|
base.OnResize(e);
|
||||||
|
GL.Viewport(0, 0, e.Width, e.Height);
|
||||||
|
foreach (IRenderObject Control in Controls)
|
||||||
|
{
|
||||||
|
if (Control.Loaded)
|
||||||
|
{
|
||||||
|
bool top = (Control.Anchor & ObjectAnchor.Top) == ObjectAnchor.Top;
|
||||||
|
bool left = (Control.Anchor & ObjectAnchor.Left) == ObjectAnchor.Left;
|
||||||
|
bool right = (Control.Anchor & ObjectAnchor.Right) == ObjectAnchor.Right;
|
||||||
|
bool bottom = (Control.Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom;
|
||||||
|
if (!top && !bottom) { Control.Anchor |= ObjectAnchor.Top; top = true; }
|
||||||
|
if (!left && !right) { Control.Anchor |= ObjectAnchor.Left; left = true; }
|
||||||
|
int lx = (left ? Control.Location.X : Size.X - Control.Distance.X - Control.Size.X);
|
||||||
|
int ly = (top ? Control.Location.Y : Size.Y - Control.Distance.Y - Control.Size.Y);
|
||||||
|
int sy = (bottom ? Size.Y - Control.Distance.Y - ly : Control.Size.Y);
|
||||||
|
int sx = (right ? Size.X - Control.Distance.X - lx : Control.Size.X);
|
||||||
|
Control.Size = new(sx, sy);
|
||||||
|
Control.Location = new(lx, ly);
|
||||||
|
if (Control is IParent)
|
||||||
|
{
|
||||||
|
IParent parent = (IParent)Control;
|
||||||
|
parent.Resize(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnResize(ResizeEventArgs e)
|
||||||
|
{
|
||||||
|
Resize(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartRender()
|
||||||
|
{
|
||||||
|
Context.MakeCurrent();
|
||||||
|
while (Exists && IsVisible && !IsExiting)
|
||||||
|
{
|
||||||
|
DrawFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawFrame()
|
||||||
|
{
|
||||||
|
ProcessEvents();
|
||||||
|
GL.ClearColor(BackgroundColor.R, BackgroundColor.G, BackgroundColor.B, (BackgroundColor.A * -1) + 1);
|
||||||
|
IEnumerable<IRenderObject> needload = Controls.Where(a => a.Loaded == false);
|
||||||
|
|
||||||
|
if (needload.Any())
|
||||||
|
{
|
||||||
|
foreach (IRenderObject obj in needload)
|
||||||
|
{
|
||||||
|
obj.LoadToParent(this, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
||||||
|
foreach (IRenderObject obj in Controls)
|
||||||
|
{
|
||||||
|
if (obj.Loaded) obj.Draw();
|
||||||
|
}
|
||||||
|
Context.SwapBuffers();
|
||||||
|
Thread.Sleep(8);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user