Files
MagicSetEditor2/src/gui/image_slice_window.hpp
T
Brendan Hagan c5d2bcf9d0 fix: apply image slice scale after slice window to avoid mask issues
MSE draws masks on the slice window and expects the sizes to be equivalent. This was presenting problems with the way I was trying to do internal scale as I was applying the scale upfront as the slice window loads and would need to scale the mask to match. Instead, applying the scale only when the output is generated from the slice window.
2022-07-09 14:51:59 -04:00

198 lines
6.7 KiB
C++

//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
#pragma once
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
class ImageSlicePreview;
class ImageSliceSelector;
class wxSpinEvent;
class wxSpinCtrl;
DECLARE_POINTER_TYPE(AlphaMask);
// ----------------------------------------------------------------------------- : ImageSlice
/// Which option is just changed, and therefore more important?
enum PreferedProperty
{ PREFER_NONE
, PREFER_WIDTH
, PREFER_HEIGHT
};
/// A slice of an image, i.e. a selected rectangle
class ImageSlice {
public:
ImageSlice(const Image& source, const wxSize& target_size);
Image source; ///< The source image
wxSize target_size; ///< Size of the target image
Color background; ///< Color for areas outside the source image
wxRect selection; ///< Area to slect from source
bool allow_outside;
bool aspect_fixed; ///< Aspect ratio lock?
// Filters
bool sharpen;
int sharpen_amount;
/// Enforce relations between values
void constrain(PreferedProperty prefer = PREFER_NONE);
/// Attempt to center the current constraints
void centerSelection();
/// Get the sliced image
Image getSlice(double scale = 1.0) const;
// Zoom factor
inline double zoomX() const { return target_size.GetWidth() / (double)selection.width; }
inline double zoomY() const { return target_size.GetHeight() / (double)selection.height; }
inline void zoomX(double zoom) { selection.width = int(target_size.GetWidth() / zoom); }
inline void zoomY(double zoom) { selection.height = int(target_size.GetHeight() / zoom); }
};
// ----------------------------------------------------------------------------- : ImageSliceWindow
/// Dialog for selecting a slice of an image
class ImageSliceWindow : public wxDialog {
public:
ImageSliceWindow(Window* parent, const Image& source, const wxSize& target_size, const AlphaMask& target_mask);
/// Return the sliced image
Image getImage(double scale) const;
// --------------------------------------------------- : Data
private:
// The slice we are extracting
ImageSlice slice;
// Gui items
ImageSlicePreview* preview;
ImageSliceSelector* selector;
wxRadioBox* size;
wxSpinCtrl* top, *left, *width, *height;
wxCheckBox* fix_aspect;
wxSpinCtrl* zoom, *zoom_x, *zoom_y;
wxSizer* zoom_sizer, *zoom_fixed, *zoom_free;
wxCheckBox* sharpen;
wxSlider* sharpen_amount;
bool initialized; // is the gui initialized?
// --------------------------------------------------- : Events
DECLARE_EVENT_TABLE();
void onOk (wxCommandEvent&);
void onSize (wxSizeEvent&);
void onChangeSize (wxCommandEvent&);
void onChangeLeft (wxCommandEvent&);
void onChangeTop (wxCommandEvent&);
void onChangeWidth (wxCommandEvent&);
void onChangeHeight (wxCommandEvent&);
void onSelectionCenter(wxCommandEvent&);
void onChangeFixAspect (wxCommandEvent&);
void onChangeZoom (wxSpinEvent&);
void onChangeZoomX (wxSpinEvent&);
void onChangeZoomY (wxSpinEvent&);
void onChangeSharpen (wxCommandEvent&);
void onChangeSharpenAmount(wxScrollEvent&);
// Something changed in the selector control, update controls and selection displays
void onSliceChange(wxCommandEvent&);
// --------------------------------------------------- : Updating
// The manual controls were changed
void onUpdateFromControl(PreferedProperty prefer = PREFER_NONE);
// Update the values in the controls
void updateControls();
};
// ----------------------------------------------------------------------------- : ImageSlicePreview
/// A preview of the sliced image
class ImageSlicePreview : public wxControl {
public:
ImageSlicePreview(Window* parent, int id, ImageSlice& slice, const AlphaMask& mask);
/// Notify that the slice was updated
void update();
// --------------------------------------------------- : Data
private:
Bitmap bitmap;
ImageSlice& slice;
const AlphaMask& mask;
bool mouse_down;
int mouseX, mouseY; ///< starting mouse position
wxRect start_selection; ///< selection in slice at start of dragging
// --------------------------------------------------- : Events
DECLARE_EVENT_TABLE();
wxSize DoGetBestSize() const override;
void onLeftDown(wxMouseEvent&);
void onLeftUp (wxMouseEvent&);
void onMotion (wxMouseEvent&);
void onLoseCapture(wxMouseCaptureLostEvent&);
void onPaint(wxPaintEvent&);
void draw(DC& dc);
};
// ----------------------------------------------------------------------------- : ImageSliceSelector
// A overview of the slicing of the image, allows to select the sliced area
class ImageSliceSelector : public wxControl {
public:
ImageSliceSelector(Window* parent, int id, ImageSlice& slice);
/// Notify that the slice was updated
void update();
// --------------------------------------------------- : Data
private:
ImageSlice& slice;
Bitmap bitmap, bitmap_no_sel; ///< Bitmaps showing selection
bool mouse_down;
int mouseX, mouseY; ///< starting mouse position
int dragX, dragY; ///< corner that is being dragged
wxRect start_selection; ///< selection in slice at start of dragging
double scaleX, scaleY; ///< Amount the source image is scaled to fit in this control
static const int border = 8;
// --------------------------------------------------- : Events
DECLARE_EVENT_TABLE();
void onLeftDown(wxMouseEvent&);
void onLeftUp (wxMouseEvent&);
void onMotion (wxMouseEvent&);
void onLoseCapture(wxMouseCaptureLostEvent&);
void onPaint(wxPaintEvent&);
void onSize(wxSizeEvent&);
// Is the mouse on a (scale) handle?
bool onHandle(const wxMouseEvent& ev, int dx, int dy) const;
// Is the mouse on any handle?
bool onAnyHandle(const wxMouseEvent& ev, int* dxOut, int* dyOut) const;
// Return the position of a handle, dx,dy in {-1,0,1}
wxPoint handlePos(int dx, int dy) const;
void draw(DC& dc);
// Draw a handle, dx and dy indicate the side, can be {-1,0,1}
void drawHandle(DC& dc, int dx, int dy);
void createBitmap();
};