|
|
@ -52,9 +52,15 @@ public class CameraInfo { |
|
|
|
public static readonly CameraInfo IPHONE_12_MINI = new(new Vector2i(4032, 3024)); |
|
|
|
} |
|
|
|
|
|
|
|
public enum ToolState { |
|
|
|
Active, |
|
|
|
Done, |
|
|
|
Canceled |
|
|
|
} |
|
|
|
|
|
|
|
public interface ITool { |
|
|
|
void SetActivePhoto(Photo photo); |
|
|
|
void HandleInput(UiGeometry geometry, KeyboardState input, MouseState mouse, Game game); |
|
|
|
ToolState HandleInput(UiGeometry geometry, KeyboardState input, MouseState mouse, Game game); |
|
|
|
string Status(); |
|
|
|
void Draw(UiGeometry geometry, Game game); |
|
|
|
} |
|
|
@ -66,29 +72,32 @@ public class ViewTool : ITool { |
|
|
|
activePhoto = photo; |
|
|
|
} |
|
|
|
|
|
|
|
public void HandleInput(UiGeometry geometry, KeyboardState input, MouseState mouse, Game game) { |
|
|
|
public ToolState HandleInput(UiGeometry geometry, KeyboardState input, MouseState mouse, Game game) { |
|
|
|
return ToolState.Active; |
|
|
|
} |
|
|
|
|
|
|
|
public string Status() { |
|
|
|
return ""; |
|
|
|
return "view"; |
|
|
|
} |
|
|
|
|
|
|
|
public void Draw(UiGeometry geometry, Game game) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// FIXME: remove unneeded dependencies on "Game" or at least refactor them a bit.
|
|
|
|
public class CropTool : ITool { |
|
|
|
|
|
|
|
Photo? activePhoto; |
|
|
|
Vector2i mouseDragStart; |
|
|
|
Vector2i mouseDragEnd; |
|
|
|
string status = ""; |
|
|
|
|
|
|
|
public void SetActivePhoto(Photo photo) { |
|
|
|
activePhoto = photo; |
|
|
|
} |
|
|
|
|
|
|
|
public void HandleInput(UiGeometry geometry, KeyboardState input, MouseState mouse, Game game) { |
|
|
|
public ToolState HandleInput(UiGeometry geometry, KeyboardState input, MouseState mouse, Game game) { |
|
|
|
Vector2i mousePosition = (Vector2i) mouse.Position; |
|
|
|
|
|
|
|
if (mouse.IsButtonPressed(MouseButton.Button1)) { |
|
|
@ -104,15 +113,23 @@ public class CropTool : ITool { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (input.IsKeyPressed(Keys.Escape)) { |
|
|
|
mouseDragStart = new(-1, -1); |
|
|
|
mouseDragEnd = new(-1, -1); |
|
|
|
} |
|
|
|
Vector2i start = game.ScreenToImage(mouseDragStart); |
|
|
|
// FIXME: this needs to be the actual width of the computed box.
|
|
|
|
Vector2i size = game.ScreenToImage(mouseDragEnd) - start; |
|
|
|
|
|
|
|
status = $"({start.X}, {start.Y}) {size.X}x{size.Y}"; |
|
|
|
|
|
|
|
// FIXME: crop should be a modal tool that starts with C and ends with Enter or Escape.
|
|
|
|
if (input.IsKeyPressed(Keys.Enter)) { |
|
|
|
ApplyCrop(game); |
|
|
|
return ToolState.Done; |
|
|
|
} |
|
|
|
|
|
|
|
if (input.IsKeyPressed(Keys.Escape)) { |
|
|
|
activePhoto.CropRectangle = Rectangle.Empty; |
|
|
|
return ToolState.Canceled; |
|
|
|
} |
|
|
|
|
|
|
|
return ToolState.Active; |
|
|
|
} |
|
|
|
|
|
|
|
// left, right, top, bottom
|
|
|
@ -171,7 +188,7 @@ public class CropTool : ITool { |
|
|
|
} |
|
|
|
|
|
|
|
public string Status() { |
|
|
|
return "crop"; |
|
|
|
return "[crop] " + status; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -754,7 +771,9 @@ public static class Util { |
|
|
|
} |
|
|
|
|
|
|
|
public class Game : GameWindow { |
|
|
|
public Game(GameWindowSettings gwSettings, NativeWindowSettings nwSettings) : base(gwSettings, nwSettings) {} |
|
|
|
public Game(GameWindowSettings gwSettings, NativeWindowSettings nwSettings) : base(gwSettings, nwSettings) { |
|
|
|
activeTool = viewTool; |
|
|
|
} |
|
|
|
|
|
|
|
private static string outputRoot = @"c:\users\colin\desktop\totte-output"; |
|
|
|
// private static string outputRoot = @"c:\users\colin\pictures\photos";
|
|
|
@ -785,7 +804,8 @@ public class Game : GameWindow { |
|
|
|
HashSet<Photo> loadedImages = new(); |
|
|
|
HashSet<Photo> loadingImages = new(); |
|
|
|
readonly object loadedImagesLock = new(); |
|
|
|
ITool activeTool = new CropTool(); |
|
|
|
readonly ViewTool viewTool = new ViewTool(); |
|
|
|
ITool activeTool; |
|
|
|
int photoIndex = 0; |
|
|
|
int ribbonIndex = 0; |
|
|
|
Vector2i mousePosition; |
|
|
@ -951,8 +971,21 @@ public class Game : GameWindow { |
|
|
|
zoomLevel = 16f; |
|
|
|
} |
|
|
|
|
|
|
|
// Handle tool switching.
|
|
|
|
if (activeTool == viewTool) { |
|
|
|
if (input.IsKeyPressed(Keys.C)) { |
|
|
|
activeTool = new CropTool(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Delegate input to the active tool.
|
|
|
|
activeTool.SetActivePhoto(photos[photoIndex]); |
|
|
|
activeTool.HandleInput(geometry, KeyboardState, MouseState, this); |
|
|
|
ToolState state = activeTool.HandleInput(geometry, KeyboardState, MouseState, this); |
|
|
|
|
|
|
|
// Change back to the default tool if the active tool is done.
|
|
|
|
if (state != ToolState.Active) { |
|
|
|
activeTool = viewTool; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void FilterByRating(int rating) { |
|
|
@ -1186,15 +1219,13 @@ public class Game : GameWindow { |
|
|
|
if (activePhoto.Loaded) { |
|
|
|
DrawText($"{(scale * 100):F1}%", geometry.StatusBox.Min.X, y); |
|
|
|
} |
|
|
|
DrawText($"({mousePosition.X}, {mousePosition.Y})", geometry.StatusBox.Min.X + 72, y); |
|
|
|
Vector2i imagePosition = ScreenToImage(mousePosition); |
|
|
|
DrawText($"({imagePosition.X}, {imagePosition.Y})", geometry.StatusBox.Min.X + 320, y); |
|
|
|
DrawText(activeTool.Status(), geometry.StatusBox.Min.X + 72, y); |
|
|
|
} |
|
|
|
|
|
|
|
public Vector2i ScreenToImage(int x, int y) { |
|
|
|
return new( |
|
|
|
(int) ((x - activeOffset.X) / activeScale), |
|
|
|
(int) ((y - activeOffset.Y) / activeScale)); |
|
|
|
int rx = (int) ((x - activeOffset.X) / activeScale); |
|
|
|
int ry = (int) ((y - activeOffset.Y) / activeScale); |
|
|
|
return new(rx, ry); |
|
|
|
} |
|
|
|
|
|
|
|
public Vector2i ScreenToImage(Vector2i position) { |
|
|
|