|
@ -57,15 +57,54 @@ public enum ToolStatus { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class Transform { |
|
|
|
|
|
// FIXME: move scale and offset into Photo itself?
|
|
|
|
|
|
float activeScale; |
|
|
|
|
|
Vector2i activeOffset; |
|
|
|
|
|
Photo photo; |
|
|
|
|
|
|
|
|
|
|
|
public Transform(float scale, Vector2i offset, Photo photo) { |
|
|
|
|
|
activeScale = scale; |
|
|
|
|
|
activeOffset = offset; |
|
|
|
|
|
this.photo = photo; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Vector2i ScreenToImageDelta(int x, int y) { |
|
|
|
|
|
return new((int) (x / activeScale), (int) (y / activeScale)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Vector2i ScreenToImage(int x, int y) { |
|
|
|
|
|
int rx = (int) ((x - activeOffset.X) / activeScale); |
|
|
|
|
|
int ry = (int) ((y - activeOffset.Y) / activeScale); |
|
|
|
|
|
rx = Math.Clamp(rx, 0, photo.Size.X); |
|
|
|
|
|
ry = Math.Clamp(ry, 0, photo.Size.Y); |
|
|
|
|
|
return new(rx, ry); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Vector2i ScreenToImage(Vector2i position) { |
|
|
|
|
|
return ScreenToImage(position.X, position.Y); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Vector2i ImageToScreen(int x, int y) { |
|
|
|
|
|
int rx = (int) ((x * activeScale) + activeOffset.X); |
|
|
|
|
|
int ry = (int) ((y * activeScale) + activeOffset.Y); |
|
|
|
|
|
return new(rx, ry); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Vector2i ImageToScreen(Vector2i position) { |
|
|
|
|
|
return ImageToScreen(position.X, position.Y); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
public interface ITool { |
|
|
public interface ITool { |
|
|
ToolStatus HandleInput(KeyboardState input, MouseState mouse, Game game); |
|
|
|
|
|
|
|
|
ToolStatus HandleInput(KeyboardState input, MouseState mouse, Transform transform); |
|
|
string Status(); |
|
|
string Status(); |
|
|
void Draw(UiGeometry geometry, Game game); |
|
|
void Draw(UiGeometry geometry, Game game); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class ViewTool : ITool { |
|
|
public class ViewTool : ITool { |
|
|
public ToolStatus HandleInput(KeyboardState input, MouseState mouse, Game game) { |
|
|
|
|
|
|
|
|
public ToolStatus HandleInput(KeyboardState input, MouseState mouse, Transform transform) { |
|
|
return ToolStatus.Active; |
|
|
return ToolStatus.Active; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -78,7 +117,6 @@ public class ViewTool : ITool { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// FIXME: remove unneeded dependencies on "Game" or at least refactor them a bit.
|
|
|
|
|
|
public class CropTool : ITool { |
|
|
public class CropTool : ITool { |
|
|
|
|
|
|
|
|
Photo photo; |
|
|
Photo photo; |
|
@ -93,9 +131,9 @@ public class CropTool : ITool { |
|
|
mouseDragEnd = new(photo.CropRectangle.Right, photo.CropRectangle.Bottom); |
|
|
mouseDragEnd = new(photo.CropRectangle.Right, photo.CropRectangle.Bottom); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public ToolStatus HandleInput(KeyboardState input, MouseState mouse, Game game) { |
|
|
|
|
|
|
|
|
public ToolStatus HandleInput(KeyboardState input, MouseState mouse, Transform transform) { |
|
|
Vector2i mousePosition = (Vector2i) mouse.Position; |
|
|
Vector2i mousePosition = (Vector2i) mouse.Position; |
|
|
Vector2i imagePosition = game.ScreenToImage(mousePosition); |
|
|
|
|
|
|
|
|
Vector2i imagePosition = transform.ScreenToImage(mousePosition); |
|
|
|
|
|
|
|
|
if (mouse.IsButtonPressed(MouseButton.Button1)) { |
|
|
if (mouse.IsButtonPressed(MouseButton.Button1)) { |
|
|
dragging = photo.CropRectangle.Contains(imagePosition.X, imagePosition.Y); |
|
|
dragging = photo.CropRectangle.Contains(imagePosition.X, imagePosition.Y); |
|
@ -118,7 +156,7 @@ public class CropTool : ITool { |
|
|
} else { |
|
|
} else { |
|
|
if (mouse.IsButtonDown(MouseButton.Button1)) { |
|
|
if (mouse.IsButtonDown(MouseButton.Button1)) { |
|
|
Vector2 delta = mouse.Delta; |
|
|
Vector2 delta = mouse.Delta; |
|
|
Vector2i imageDelta = game.ScreenToImageDelta((int) delta.X, (int) delta.Y); |
|
|
|
|
|
|
|
|
Vector2i imageDelta = transform.ScreenToImageDelta((int) delta.X, (int) delta.Y); |
|
|
photo.CropRectangle.Offset(imageDelta.X, imageDelta.Y); |
|
|
photo.CropRectangle.Offset(imageDelta.X, imageDelta.Y); |
|
|
if (photo.CropRectangle.Left < 0) { |
|
|
if (photo.CropRectangle.Left < 0) { |
|
|
photo.CropRectangle.Offset(-photo.CropRectangle.Left, 0); |
|
|
photo.CropRectangle.Offset(-photo.CropRectangle.Left, 0); |
|
@ -406,6 +444,7 @@ public class Game : GameWindow { |
|
|
Vector2i mousePosition; |
|
|
Vector2i mousePosition; |
|
|
float activeScale = 1f; |
|
|
float activeScale = 1f; |
|
|
Vector2i activeOffset; |
|
|
Vector2i activeOffset; |
|
|
|
|
|
Transform transform = new(1f, Vector2i.Zero, null); |
|
|
Shader shader = new(); |
|
|
Shader shader = new(); |
|
|
Matrix4 projection; |
|
|
Matrix4 projection; |
|
|
float zoomLevel = 0f; |
|
|
float zoomLevel = 0f; |
|
@ -574,7 +613,7 @@ public class Game : GameWindow { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Delegate input to the active tool.
|
|
|
// Delegate input to the active tool.
|
|
|
ToolStatus status = activeTool.HandleInput(KeyboardState, MouseState, this); |
|
|
|
|
|
|
|
|
ToolStatus status = activeTool.HandleInput(KeyboardState, MouseState, transform); |
|
|
|
|
|
|
|
|
// Change back to the default tool if the active tool is done.
|
|
|
// Change back to the default tool if the active tool is done.
|
|
|
if (status != ToolStatus.Active) { |
|
|
if (status != ToolStatus.Active) { |
|
@ -642,9 +681,9 @@ public class Game : GameWindow { |
|
|
GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); |
|
|
GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); |
|
|
|
|
|
|
|
|
// Load photos from a directory.
|
|
|
// Load photos from a directory.
|
|
|
// string[] files = Directory.GetFiles(@"c:\users\colin\desktop\photos-test\");
|
|
|
|
|
|
|
|
|
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\2023\07\14\");
|
|
|
string[] files = Directory.GetFiles(@"c:\users\colin\pictures\photos\2023\07\23\"); |
|
|
|
|
|
|
|
|
// string[] files = Directory.GetFiles(@"c:\users\colin\pictures\photos\2023\07\23\");
|
|
|
// string[] files = Directory.GetFiles(@"G:\DCIM\100EOSR6\");
|
|
|
// string[] files = Directory.GetFiles(@"G:\DCIM\100EOSR6\");
|
|
|
// string[] files = Directory.GetFiles(@"c:\users\colin\desktop\totte-output\2023\07\31");
|
|
|
// string[] files = Directory.GetFiles(@"c:\users\colin\desktop\totte-output\2023\07\31");
|
|
|
// string[] files = Directory.GetFiles(@"C:\Users\colin\Pictures\photos\2018\06\23");
|
|
|
// string[] files = Directory.GetFiles(@"C:\Users\colin\Pictures\photos\2018\06\23");
|
|
@ -777,6 +816,7 @@ public class Game : GameWindow { |
|
|
Vector2i center = (Vector2i) geometry.PhotoBox.Center; |
|
|
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); |
|
|
activeOffset = new(photoBox.Min.X, photoBox.Min.Y); |
|
|
|
|
|
transform = new Transform(activeScale, activeOffset, activePhoto); |
|
|
DrawTexture(active, photoBox); |
|
|
DrawTexture(active, photoBox); |
|
|
for (int i = 0; i < 5; i++) { |
|
|
for (int i = 0; i < 5; i++) { |
|
|
Texture star = (activePhoto.Rating > i) ? STAR_FILLED : STAR_EMPTY; |
|
|
Texture star = (activePhoto.Rating > i) ? STAR_FILLED : STAR_EMPTY; |
|
@ -827,8 +867,8 @@ public class Game : GameWindow { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Vector2i leftTop = ImageToScreen(activePhoto.CropRectangle.Left, activePhoto.CropRectangle.Top); |
|
|
|
|
|
Vector2i rightBottom = ImageToScreen(activePhoto.CropRectangle.Right, activePhoto.CropRectangle.Bottom); |
|
|
|
|
|
|
|
|
Vector2i leftTop = transform.ImageToScreen(activePhoto.CropRectangle.Left, activePhoto.CropRectangle.Top); |
|
|
|
|
|
Vector2i rightBottom = transform.ImageToScreen(activePhoto.CropRectangle.Right, activePhoto.CropRectangle.Bottom); |
|
|
var (left, top) = leftTop; |
|
|
var (left, top) = leftTop; |
|
|
var (right, bottom) = rightBottom; |
|
|
var (right, bottom) = rightBottom; |
|
|
|
|
|
|
|
@ -846,32 +886,6 @@ public class Game : GameWindow { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public Vector2i ScreenToImageDelta(int x, int y) { |
|
|
|
|
|
return new((int) (x / activeScale), (int) (y / activeScale)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Vector2i ScreenToImage(int x, int y) { |
|
|
|
|
|
int rx = (int) ((x - activeOffset.X) / activeScale); |
|
|
|
|
|
int ry = (int) ((y - activeOffset.Y) / activeScale); |
|
|
|
|
|
rx = Math.Clamp(rx, 0, photos[photoIndex].Size.X); |
|
|
|
|
|
ry = Math.Clamp(ry, 0, photos[photoIndex].Size.Y); |
|
|
|
|
|
return new(rx, ry); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Vector2i ScreenToImage(Vector2i position) { |
|
|
|
|
|
return ScreenToImage(position.X, position.Y); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Vector2i ImageToScreen(int x, int y) { |
|
|
|
|
|
int rx = (int) ((x * activeScale) + activeOffset.X); |
|
|
|
|
|
int ry = (int) ((y * activeScale) + activeOffset.Y); |
|
|
|
|
|
return new(rx, ry); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public Vector2i ImageToScreen(Vector2i position) { |
|
|
|
|
|
return ImageToScreen(position.X, position.Y); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void DrawTexture(Texture texture, int x, int y) { |
|
|
public void DrawTexture(Texture texture, int x, int y) { |
|
|
DrawTexture(texture, Util.MakeBox(x, y, texture.Size.X, texture.Size.Y)); |
|
|
DrawTexture(texture, Util.MakeBox(x, y, texture.Size.X, texture.Size.Y)); |
|
|
} |
|
|
} |
|
|