diff --git a/Photo.cs b/Photo.cs index e25db1e..f6a9c0b 100644 --- a/Photo.cs +++ b/Photo.cs @@ -8,7 +8,6 @@ using System.Xml.Linq; namespace SemiColinGames; - public class Photo { public string Filename; public bool Loaded = false; diff --git a/Program.cs b/Program.cs index a4e94ed..404d889 100644 --- a/Program.cs +++ b/Program.cs @@ -11,11 +11,9 @@ using SixLabors.ImageSharp.Drawing; using SixLabors.ImageSharp.Formats.Jpeg; using System; using System.Diagnostics; -using System.Runtime.CompilerServices; namespace SemiColinGames; - public class FpsCounter { private readonly int[] frameTimes = new int[30]; private double fps = 0; @@ -209,57 +207,6 @@ public class CropTool : ITool { } -public class Texture : IDisposable { - public int Handle; - public Vector2i Size; - - private static int maxHandle = -1; - private bool disposedValue = false; - - public Texture(Image image) { - Size = new Vector2i(image.Width, image.Height); - byte[] pixelBytes = new byte[Size.X * Size.Y * Unsafe.SizeOf()]; - image.CopyPixelDataTo(pixelBytes); - - Handle = GL.GenTexture(); - if (Handle > maxHandle) { - // Console.WriteLine("GL.GenTexture #" + Handle); - maxHandle = Handle; - } - GL.ActiveTexture(TextureUnit.Texture0); - GL.BindTexture(TextureTarget.Texture2D, Handle); - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Size.X, Size.Y, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixelBytes); - //GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.LinearMipmapLinear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) TextureMagFilter.Nearest); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) TextureWrapMode.ClampToBorder); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToBorder); - float[] borderColor = { 0.0f, 0.0f, 0.0f, 1.0f }; - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, borderColor); - // FIXME: should we use mipmaps? - //GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); - } - - protected virtual void Dispose(bool disposing) { - if (!disposedValue) { - GL.DeleteTexture(Handle); - disposedValue = true; - } - } - - ~Texture() { - if (!disposedValue) { - Console.WriteLine("~Texture(): resource leak? Dispose() should be called manually."); - } - } - - public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } -} - - public class UiGeometry { public static Vector2i MIN_WINDOW_SIZE = new(1024, 768); @@ -805,7 +752,8 @@ public class Game : GameWindow { Vector2i renderSize = (Vector2i) (((Vector2) active.Size) * scale); Vector2i center = (Vector2i) geometry.PhotoBox.Center; - Box2i photoBox = Util.MakeBox(center.X - renderSize.X / 2, center.Y - renderSize.Y / 2, renderSize.X, renderSize.Y); + Box2i photoBox = Util.MakeBox(center.X - renderSize.X / 2, center.Y - renderSize.Y / 2, + renderSize.X, renderSize.Y); activeOffset = new(photoBox.Min.X, photoBox.Min.Y); transform = new Transform(activeScale, activeOffset, activePhoto.Size); DrawTexture(active, photoBox); @@ -817,7 +765,8 @@ public class Game : GameWindow { DrawCropRectangle(cropActive); // Draw thumbnail boxes. - ribbonIndex = Math.Clamp(photoIndex - (geometry.ThumbnailBoxes.Count - 1) / 2, 0, Math.Max(0, photos.Count - geometry.ThumbnailBoxes.Count)); + ribbonIndex = Math.Clamp(photoIndex - (geometry.ThumbnailBoxes.Count - 1) / 2, + 0, Math.Max(0, photos.Count - geometry.ThumbnailBoxes.Count)); DrawFilledBox(geometry.ThumbnailBox, Color4.Black); for (int i = 0; i < geometry.ThumbnailBoxes.Count; i++) { if (ribbonIndex + i >= photos.Count) { diff --git a/Texture.cs b/Texture.cs new file mode 100644 index 0000000..8f9094d --- /dev/null +++ b/Texture.cs @@ -0,0 +1,55 @@ +using OpenTK.Graphics.OpenGL4; +using OpenTK.Mathematics; +using System.Runtime.CompilerServices; + +namespace SemiColinGames; + +public class Texture : IDisposable { + public int Handle; + public Vector2i Size; + + private static int maxHandle = -1; + private bool disposedValue = false; + + public Texture(Image image) { + Size = new Vector2i(image.Width, image.Height); + byte[] pixelBytes = new byte[Size.X * Size.Y * Unsafe.SizeOf()]; + image.CopyPixelDataTo(pixelBytes); + + Handle = GL.GenTexture(); + if (Handle > maxHandle) { + // Console.WriteLine("GL.GenTexture #" + Handle); + maxHandle = Handle; + } + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, Handle); + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Size.X, Size.Y, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixelBytes); + //GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.LinearMipmapLinear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) TextureMagFilter.Nearest); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) TextureWrapMode.ClampToBorder); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToBorder); + float[] borderColor = { 0.0f, 0.0f, 0.0f, 1.0f }; + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, borderColor); + // FIXME: should we use mipmaps? + //GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); + } + + protected virtual void Dispose(bool disposing) { + if (!disposedValue) { + GL.DeleteTexture(Handle); + disposedValue = true; + } + } + + ~Texture() { + if (!disposedValue) { + Console.WriteLine("~Texture(): resource leak? Dispose() should be called manually."); + } + } + + public void Dispose() { + Dispose(true); + GC.SuppressFinalize(this); + } +}