|
|
@ -139,20 +139,14 @@ void main() { |
|
|
|
} |
|
|
|
|
|
|
|
public class Photo { |
|
|
|
public Texture Texture; |
|
|
|
public bool Loaded = false; |
|
|
|
private readonly string filename; |
|
|
|
private Texture texture; |
|
|
|
private Texture placeholder; |
|
|
|
private Image<Rgba32> image; |
|
|
|
|
|
|
|
public Photo(string filename, Texture unloadedTexture) { |
|
|
|
this.filename = filename; |
|
|
|
Texture = unloadedTexture; |
|
|
|
} |
|
|
|
|
|
|
|
public void Load() { |
|
|
|
Image<Rgba32> image = Image.Load<Rgba32>(filename); |
|
|
|
|
|
|
|
Console.WriteLine("----------------------------------"); |
|
|
|
Console.WriteLine($"image loaded: {image.Width}x{image.Height}"); |
|
|
|
public Photo(Image<Rgba32> image, Texture placeholder) { |
|
|
|
this.image = image; |
|
|
|
this.placeholder = placeholder; |
|
|
|
texture = placeholder; |
|
|
|
|
|
|
|
ExifProfile? exifs = image.Metadata.ExifProfile; |
|
|
|
if (exifs != null) { |
|
|
@ -162,9 +156,15 @@ public class Photo { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
Texture = new Texture(image); |
|
|
|
Loaded = true; |
|
|
|
} |
|
|
|
|
|
|
|
public Texture Texture() { |
|
|
|
if (texture == placeholder) { |
|
|
|
texture = new Texture(image); |
|
|
|
image.Dispose(); |
|
|
|
} |
|
|
|
return texture; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public class Texture : IDisposable { |
|
|
@ -175,7 +175,6 @@ public class Texture : IDisposable { |
|
|
|
Size = new Vector2i(image.Width, image.Height); |
|
|
|
byte[] pixelBytes = new byte[Size.X * Size.Y * Unsafe.SizeOf<Rgba32>()]; |
|
|
|
image.CopyPixelDataTo(pixelBytes); |
|
|
|
image.Dispose(); |
|
|
|
|
|
|
|
Handle = GL.GenTexture(); |
|
|
|
GL.ActiveTexture(TextureUnit.Texture0); |
|
|
@ -262,6 +261,7 @@ public class Game : GameWindow { |
|
|
|
1, 2, 3 // second triangle
|
|
|
|
}; |
|
|
|
|
|
|
|
bool doneLoading = false; |
|
|
|
int VertexBufferObject; |
|
|
|
int ElementBufferObject; |
|
|
|
int VertexArrayObject; |
|
|
@ -293,7 +293,6 @@ public class Game : GameWindow { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Track keyboard repeat times for advancing up/down.
|
|
|
|
if (!input.IsKeyDown(Keys.Down)) { |
|
|
|
downTimer = Int64.MaxValue; |
|
|
@ -318,7 +317,7 @@ public class Game : GameWindow { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected override void OnLoad() { |
|
|
|
protected override async void OnLoad() { |
|
|
|
base.OnLoad(); |
|
|
|
|
|
|
|
GL.ClearColor(0f, 0f, 0f, 1f); |
|
|
@ -354,19 +353,24 @@ public class Game : GameWindow { |
|
|
|
// Load textures from JPEGs.
|
|
|
|
// string[] files = Directory.GetFiles(@"c:\users\colin\desktop\photos-test\");
|
|
|
|
string[] files = Directory.GetFiles(@"c:\users\colin\pictures\photos\2023\07\14\"); |
|
|
|
//string[] files = Directory.GetFiles(@"C:\Users\colin\Pictures\photos\2018\06\23");
|
|
|
|
|
|
|
|
List<Task<Image<Rgba32>>> imageTasks = new(); |
|
|
|
for (int i = 0; i < files.Count(); i++) { |
|
|
|
string file = files[i]; |
|
|
|
if (file.ToLower().EndsWith(".jpg")) { |
|
|
|
Photo photo = new(file, TEXTURE_WHITE); |
|
|
|
if (i == 0) { |
|
|
|
photo.Load(); |
|
|
|
} |
|
|
|
photos.Add(photo); |
|
|
|
if (photos.Count > 10) { |
|
|
|
break; |
|
|
|
} |
|
|
|
imageTasks.Add(Image.LoadAsync<Rgba32>(file)); |
|
|
|
} |
|
|
|
} |
|
|
|
Console.WriteLine(DateTime.Now); |
|
|
|
await Task.WhenAll(imageTasks); |
|
|
|
Console.WriteLine(DateTime.Now); |
|
|
|
|
|
|
|
foreach (Task<Image<Rgba32>> task in imageTasks) { |
|
|
|
Photo photo = new(task.Result, TEXTURE_WHITE); |
|
|
|
photos.Add(photo); |
|
|
|
} |
|
|
|
doneLoading = true; |
|
|
|
} |
|
|
|
|
|
|
|
protected override void OnUnload() { |
|
|
@ -375,11 +379,15 @@ public class Game : GameWindow { |
|
|
|
|
|
|
|
protected override void OnRenderFrame(FrameEventArgs e) { |
|
|
|
base.OnRenderFrame(e); |
|
|
|
if (!doneLoading) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
GL.Clear(ClearBufferMask.ColorBufferBit); |
|
|
|
GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject); |
|
|
|
GL.ActiveTexture(TextureUnit.Texture0); |
|
|
|
|
|
|
|
Texture active = photos[photoIndex].Texture; |
|
|
|
Texture active = photos[photoIndex].Texture(); |
|
|
|
|
|
|
|
// FIXME: make a function for scaling & centering one box on another.
|
|
|
|
float scaleX = 1f * geometry.PhotoBox.Size.X / active.Size.X; |
|
|
@ -390,9 +398,9 @@ public class Game : GameWindow { |
|
|
|
Vector2i center = (Vector2i) geometry.PhotoBox.Center; |
|
|
|
Box2i photoBox = Util.makeBox(center.X - renderSize.X / 2, center.Y - renderSize.Y / 2, renderSize.X, renderSize.Y); |
|
|
|
DrawTexture(active, photoBox); |
|
|
|
for (int i = 0; i < photos.Count; i++) { |
|
|
|
for (int i = 0; i < photos.Count && i < geometry.ThumbnailBoxes.Count(); i++) { |
|
|
|
Box2i box = geometry.ThumbnailBoxes[i]; |
|
|
|
DrawTexture(photos[i].Texture, box); |
|
|
|
DrawTexture(photos[i].Texture(), box); |
|
|
|
if (i == photoIndex) { |
|
|
|
DrawBox(box, 5, Color4.Black); |
|
|
|
DrawBox(box, 3, Color4.White); |
|
|
@ -402,7 +410,6 @@ public class Game : GameWindow { |
|
|
|
SwapBuffers(); |
|
|
|
} |
|
|
|
|
|
|
|
// FIXME: pull these out into a Util class and let photos be able to draw themselves?
|
|
|
|
void DrawTexture(Texture texture, Box2i box) { |
|
|
|
DrawTexture(texture, box, Color4.White); |
|
|
|
} |
|
|
|