Compare commits
3 Commits
304097177c
...
1c586a6197
Author | SHA1 | Date | |
---|---|---|---|
1c586a6197 | |||
c953fa2b47 | |||
1793fee616 |
85
Program.cs
85
Program.cs
@ -50,7 +50,7 @@ public class CameraInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public enum ToolState {
|
public enum ToolStatus {
|
||||||
Active,
|
Active,
|
||||||
Done,
|
Done,
|
||||||
Canceled
|
Canceled
|
||||||
@ -58,15 +58,15 @@ public enum ToolState {
|
|||||||
|
|
||||||
|
|
||||||
public interface ITool {
|
public interface ITool {
|
||||||
ToolState HandleInput(UiGeometry geometry, KeyboardState input, MouseState mouse, Game game);
|
ToolStatus HandleInput(KeyboardState input, MouseState mouse, Game game);
|
||||||
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 ToolState HandleInput(UiGeometry geometry, KeyboardState input, MouseState mouse, Game game) {
|
public ToolStatus HandleInput(KeyboardState input, MouseState mouse, Game game) {
|
||||||
return ToolState.Active;
|
return ToolStatus.Active;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Status() {
|
public string Status() {
|
||||||
@ -81,59 +81,82 @@ public class ViewTool : ITool {
|
|||||||
// FIXME: remove unneeded dependencies on "Game" or at least refactor them a bit.
|
// FIXME: remove unneeded dependencies on "Game" or at least refactor them a bit.
|
||||||
public class CropTool : ITool {
|
public class CropTool : ITool {
|
||||||
|
|
||||||
Photo activePhoto;
|
Photo photo;
|
||||||
Vector2i mouseDragStart;
|
Vector2i mouseDragStart;
|
||||||
Vector2i mouseDragEnd;
|
Vector2i mouseDragEnd;
|
||||||
|
bool dragging;
|
||||||
string status = "";
|
string status = "";
|
||||||
|
|
||||||
public CropTool(Photo photo) {
|
public CropTool(Photo photo) {
|
||||||
activePhoto = photo;
|
this.photo = photo;
|
||||||
|
mouseDragStart = new(photo.CropRectangle.Left, photo.CropRectangle.Top);
|
||||||
|
mouseDragEnd = new(photo.CropRectangle.Right, photo.CropRectangle.Bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ToolState HandleInput(UiGeometry geometry, KeyboardState input, MouseState mouse, Game game) {
|
public ToolStatus HandleInput(KeyboardState input, MouseState mouse, Game game) {
|
||||||
Vector2i mousePosition = (Vector2i) mouse.Position;
|
Vector2i mousePosition = (Vector2i) mouse.Position;
|
||||||
Vector2i imagePosition = game.ScreenToImage(mousePosition);
|
Vector2i imagePosition = game.ScreenToImage(mousePosition);
|
||||||
|
|
||||||
if (mouse.IsButtonPressed(MouseButton.Button1)) {
|
if (mouse.IsButtonPressed(MouseButton.Button1)) {
|
||||||
if (geometry.PhotoBox.ContainsInclusive(mousePosition)) {
|
dragging = photo.CropRectangle.Contains(imagePosition.X, imagePosition.Y);
|
||||||
mouseDragStart = imagePosition;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouse.IsButtonDown(MouseButton.Button1)) {
|
if (!dragging) {
|
||||||
if (geometry.PhotoBox.ContainsInclusive(mousePosition)) {
|
if (mouse.IsButtonPressed(MouseButton.Button1)) {
|
||||||
mouseDragEnd = imagePosition;
|
mouseDragStart = imagePosition;
|
||||||
}
|
}
|
||||||
|
if (mouse.IsButtonDown(MouseButton.Button1)) {
|
||||||
|
mouseDragEnd = imagePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
var (left, right, top, bottom) = GetCrop();
|
var (left, right, top, bottom) = GetCrop();
|
||||||
Vector2i size = new(right - left, bottom - top);
|
if (left != right && top != bottom) {
|
||||||
|
photo.CropRectangle = Rectangle.FromLTRB(left, top, right, bottom);
|
||||||
status = $"({left}, {top}) {size.X}x{size.Y}";
|
} else {
|
||||||
|
photo.CropRectangle = Rectangle.Empty;
|
||||||
Rectangle crop = Rectangle.Empty;
|
|
||||||
if (size.X > 0 && size.Y > 0) {
|
|
||||||
crop = Rectangle.FromLTRB(left, top, right, bottom);
|
|
||||||
}
|
}
|
||||||
activePhoto.CropRectangle = crop;
|
} else {
|
||||||
|
if (mouse.IsButtonDown(MouseButton.Button1)) {
|
||||||
|
Vector2 delta = mouse.Delta;
|
||||||
|
Vector2i imageDelta = game.ScreenToImageDelta((int) delta.X, (int) delta.Y);
|
||||||
|
photo.CropRectangle.Offset(imageDelta.X, imageDelta.Y);
|
||||||
|
if (photo.CropRectangle.Left < 0) {
|
||||||
|
photo.CropRectangle.Offset(-photo.CropRectangle.Left, 0);
|
||||||
|
}
|
||||||
|
if (photo.CropRectangle.Right > photo.Size.X) {
|
||||||
|
int overshoot = photo.CropRectangle.Right - photo.Size.X;
|
||||||
|
photo.CropRectangle.Offset(-overshoot, 0);
|
||||||
|
}
|
||||||
|
if (photo.CropRectangle.Top < 0) {
|
||||||
|
photo.CropRectangle.Offset(0, -photo.CropRectangle.Top);
|
||||||
|
}
|
||||||
|
if (photo.CropRectangle.Bottom > photo.Size.Y) {
|
||||||
|
int overshoot = photo.CropRectangle.Bottom - photo.Size.Y;
|
||||||
|
photo.CropRectangle.Offset(0, -overshoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle r = photo.CropRectangle;
|
||||||
|
status = $"({r.Left}, {r.Top}, {r.Right}, {r.Bottom}) {r.Width}x{r.Height}";
|
||||||
|
|
||||||
if (input.IsKeyPressed(Keys.Enter)) {
|
if (input.IsKeyPressed(Keys.Enter)) {
|
||||||
return ToolState.Done;
|
return ToolStatus.Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.IsKeyPressed(Keys.Escape)) {
|
if (input.IsKeyPressed(Keys.Escape)) {
|
||||||
activePhoto.CropRectangle = Rectangle.Empty;
|
photo.CropRectangle = Rectangle.Empty;
|
||||||
return ToolState.Canceled;
|
return ToolStatus.Canceled;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToolState.Active;
|
return ToolStatus.Active;
|
||||||
}
|
}
|
||||||
|
|
||||||
// left, right, top, bottom
|
// left, right, top, bottom
|
||||||
(int, int, int, int) GetCrop() {
|
(int, int, int, int) GetCrop() {
|
||||||
// FIXME: this expects the start point in the top left and the end point
|
// FIXME: this expects the start point in the top left and the end point
|
||||||
// in the bottom right; some sign flipping needs to occur to make anchors
|
// in the bottom right; some sign flipping needs to occur to make anchors
|
||||||
// in other direction work well.
|
// in other directions work well.
|
||||||
Vector2i start = mouseDragStart;
|
Vector2i start = mouseDragStart;
|
||||||
Vector2i end = mouseDragEnd;
|
Vector2i end = mouseDragEnd;
|
||||||
// FIXME: choose the aspect ratio based on the original image aspect ratio.
|
// FIXME: choose the aspect ratio based on the original image aspect ratio.
|
||||||
@ -551,10 +574,10 @@ public class Game : GameWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delegate input to the active tool.
|
// Delegate input to the active tool.
|
||||||
ToolState state = activeTool.HandleInput(geometry, KeyboardState, MouseState, this);
|
ToolStatus status = activeTool.HandleInput(KeyboardState, MouseState, this);
|
||||||
|
|
||||||
// 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 (state != ToolState.Active) {
|
if (status != ToolStatus.Active) {
|
||||||
activeTool = viewTool;
|
activeTool = viewTool;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -823,10 +846,14 @@ 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) {
|
public Vector2i ScreenToImage(int x, int y) {
|
||||||
int rx = (int) ((x - activeOffset.X) / activeScale);
|
int rx = (int) ((x - activeOffset.X) / activeScale);
|
||||||
rx = Math.Clamp(rx, 0, photos[photoIndex].Size.X);
|
|
||||||
int ry = (int) ((y - activeOffset.Y) / 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);
|
ry = Math.Clamp(ry, 0, photos[photoIndex].Size.Y);
|
||||||
return new(rx, ry);
|
return new(rx, ry);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user