Implement unique IDs and card linking

This commit is contained in:
GenevensiS
2025-08-11 16:17:13 +02:00
committed by GitHub
parent 13406b946c
commit 3bf9de18b1
100 changed files with 2432 additions and 1219 deletions
+152 -85
View File
@@ -13,15 +13,18 @@
#include <util/rotation.hpp>
#include <gfx/gfx.hpp>
#include <wx/spinctrl.h>
#include <wx/dcbuffer.h>
#include <wx/dcbuffer.h>
map<String, String> ImageSliceWindow::previously_used_settings_path;
map<pair<String, String>, pair<wxRect, int>> ImageSliceWindow::previously_used_settings_value;
// ----------------------------------------------------------------------------- : ImageSlice
ImageSlice::ImageSlice(const Image& source, const wxSize& target_size)
: source(source), target_size(target_size)
ImageSlice::ImageSlice(const Image& source, const String& source_path, const String& card_name, const wxSize& target_size)
: source(source), source_path(source_path), card_name(card_name), target_size(target_size)
, selection(0, 0, source.GetWidth(), source.GetHeight())
, allow_outside(false), aspect_fixed(true)
, sharpen(false), sharpen_amount(25)
, sharpen(false), sharpen_amount(0)
{}
void ImageSlice::constrain(PreferedProperty prefer) {
@@ -51,24 +54,24 @@ void ImageSlice::constrain(PreferedProperty prefer) {
}
}
void ImageSlice::centerSelection() {
centerSelectionHorizontally();
void ImageSlice::centerSelection() {
centerSelectionHorizontally();
centerSelectionVertically();
}
void ImageSlice::centerSelectionHorizontally() {
}
void ImageSlice::centerSelectionHorizontally() {
if (selection.GetWidth() < source.GetWidth()) {
selection.x = ((source.GetWidth() - selection.GetWidth()) / 2);
}
}
void ImageSlice::centerSelectionVertically() {
if (selection.GetHeight() < source.GetHeight()) {
selection.y = ((source.GetHeight() - selection.GetHeight()) / 2);
}
}
Image ImageSlice::getSlice(double scale) const {
void ImageSlice::centerSelectionVertically() {
if (selection.GetHeight() < source.GetHeight()) {
selection.y = ((source.GetHeight() - selection.GetHeight()) / 2);
}
}
Image ImageSlice::getSlice(double scale) const {
wxSize scaled_target_size = target_size * scale;
if (selection.width == scaled_target_size.GetWidth() && selection.height == scaled_target_size.GetHeight() && selection.x == 0 && selection.y == 0) {
// exactly the right size
@@ -93,20 +96,31 @@ DEFINE_EVENT_TYPE(EVENT_SLICE_CHANGED);
// ----------------------------------------------------------------------------- : ImageSliceWindow
ImageSliceWindow::ImageSliceWindow(Window* parent, const Image& source, const wxSize& target_size, const AlphaMask& mask)
ImageSliceWindow::ImageSliceWindow(Window* parent, const Image& source, const String& filename, const String& cardname, const wxSize& target_size, const AlphaMask& mask)
: wxDialog(parent,wxID_ANY,_TITLE_("slice image"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE)
, slice(source, target_size)
, slice(source, filename, cardname, target_size)
, initialized(false)
{
// init slice
slice.constrain();
slice.centerSelection();
// init slice
pair<String, String> settings_entry = { filename, cardname };
if (previously_used_settings_value.find(settings_entry) != previously_used_settings_value.end()) {
//slice.allow_outside = true; this currrently crashes
slice.aspect_fixed = false;
slice.sharpen = true;
slice.sharpen_amount = previously_used_settings_value[settings_entry].second;
slice.selection = previously_used_settings_value[settings_entry].first;
slice.constrain();
}
else {
slice.constrain();
slice.centerSelection();
}
// init controls
const wxPoint defPos = wxDefaultPosition;
const wxSize spinSize(80,-1);
selector = new ImageSliceSelector(this, ID_SELECTOR, slice);
preview = new ImageSlicePreview (this, ID_PREVIEW, slice, mask);
preview = new ImageSlicePreview (this, ID_PREVIEW, slice, mask, 0);
String sizes[] = { _LABEL_("original size")
, _LABEL_("size to fit")
@@ -135,7 +149,14 @@ ImageSliceWindow::ImageSliceWindow(Window* parent, const Image& source, const wx
sharpen_amount = new wxSlider(this, ID_SHARPEN_AMOUNT, 0, 0, 100);
// allowOutside= new CheckBox(&this, idSliceAllowOutside, _("Allow selection outside source"))
// bgColor = new ColorSelector(&this, wxID_ANY)
String grids[] = { _LABEL_("none")
, _LABEL_("grid halves")
, _LABEL_("grid thirds")
, _LABEL_("grid fourths")
, _LABEL_("grid fifths") };
grid = new wxRadioBox(this, ID_GRID, _LABEL_("grid"), defPos, wxDefaultSize, 5, grids, 1);
// init sizers
wxSizer* s = new wxBoxSizer(wxVERTICAL);
// top row: image editors
@@ -164,22 +185,22 @@ ImageSliceWindow::ImageSliceWindow(Window* parent, const Image& source, const wx
s7->Add(width, 0, wxEXPAND);
s7->Add(new wxStaticText(this, wxID_ANY, _LABEL_("selection height")), 0, wxALIGN_CENTER_VERTICAL);
s7->Add(height, 0, wxEXPAND);
s7->Add(new wxStaticText(this, wxID_ANY, _LABEL_("selection center")), 0, wxALIGN_CENTER_VERTICAL);
wxBoxSizer* s7A = new wxBoxSizer(wxHORIZONTAL);
wxBitmapButton* center_vertically_button = new wxBitmapButton(this, ID_SELECTION_CENTER_VERTICALLY, wxBitmap(load_resource_image(_("shape_align_middle"))));
center_vertically_button->SetToolTip(_LABEL_("selection center vertically"));
s7A->Add(center_vertically_button);
s7A->AddStretchSpacer();
wxBitmapButton* center_horizontally_button = new wxBitmapButton(this, ID_SELECTION_CENTER_HORIZONTALLY, wxBitmap(load_resource_image(_("shape_align_center"))));
center_horizontally_button->SetToolTip(_LABEL_("selection center horizontally"));
s7A->Add(center_horizontally_button);
s7A->AddStretchSpacer();
wxBitmapButton* center_button = new wxBitmapButton(this, ID_SELECTION_CENTER, wxBitmap(load_resource_image(_("shape_align_both"))));
center_button->SetToolTip(_LABEL_("selection center both"));
s7A->Add(center_button);
s7->Add(new wxStaticText(this, wxID_ANY, _LABEL_("selection center")), 0, wxALIGN_CENTER_VERTICAL);
wxBoxSizer* s7A = new wxBoxSizer(wxHORIZONTAL);
wxBitmapButton* center_vertically_button = new wxBitmapButton(this, ID_SELECTION_CENTER_VERTICALLY, wxBitmap(load_resource_image(_("shape_align_middle"))));
center_vertically_button->SetToolTip(_LABEL_("selection center vertically"));
s7A->Add(center_vertically_button);
s7A->AddStretchSpacer();
wxBitmapButton* center_horizontally_button = new wxBitmapButton(this, ID_SELECTION_CENTER_HORIZONTALLY, wxBitmap(load_resource_image(_("shape_align_center"))));
center_horizontally_button->SetToolTip(_LABEL_("selection center horizontally"));
s7A->Add(center_horizontally_button);
s7A->AddStretchSpacer();
wxBitmapButton* center_button = new wxBitmapButton(this, ID_SELECTION_CENTER, wxBitmap(load_resource_image(_("shape_align_both"))));
center_button->SetToolTip(_LABEL_("selection center both"));
s7A->Add(center_button);
s7->Add(s7A, 1, wxEXPAND, 0);
s6->Add(s7, 1, wxEXPAND | wxALL, 4);
s5->Add(s6, 0, wxEXPAND | wxALL, 4);
@@ -206,6 +227,8 @@ ImageSliceWindow::ImageSliceWindow(Window* parent, const Image& source, const wx
sB->Add(sharpen_amount, 0, wxEXPAND | wxALL, 4);
s5->Add(sB, 0, wxEXPAND | wxALL, 4);
s5->AddStretchSpacer(1);
s5->Add(grid, 0, wxEXPAND | wxALL, 4);
s5->AddStretchSpacer(1);
s->Add(s5, 0, wxEXPAND);
s->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxALL, 8);
s->SetSizeHints(this);
@@ -219,8 +242,11 @@ void ImageSliceWindow::onOk(wxCommandEvent&) {
EndModal(wxID_OK);
}
Image ImageSliceWindow::getImage(double scale) const {
return slice.getSlice(scale);
Image ImageSliceWindow::getImage(double scale) const {
Image img = slice.getSlice(scale);
previously_used_settings_path[slice.card_name] = slice.source_path;
previously_used_settings_value[{ slice.source_path, slice.card_name }] = { slice.selection, slice.sharpen_amount };
return img;
}
// ----------------------------------------------------------------------------- : ImageSliceWindow : Controls
@@ -249,7 +275,13 @@ void ImageSliceWindow::onChangeSize(wxCommandEvent&) {
slice.aspect_fixed = false;
onUpdateFromControl();
}
}
}
void ImageSliceWindow::onChangeGrid(wxCommandEvent&) {
if (!initialized) return;
preview->grid = grid->GetSelection();
preview->update();
}
void ImageSliceWindow::onChangeLeft(wxCommandEvent&) {
if (!initialized) return;
@@ -322,16 +354,16 @@ void ImageSliceWindow::onUpdateFromControl(PreferedProperty prefer) {
updateControls();
}
void ImageSliceWindow::onSelectionCenter(wxCommandEvent& ev) {
void ImageSliceWindow::onSelectionCenter(wxCommandEvent& ev) {
switch (ev.GetId()) {
case ID_SELECTION_CENTER:
slice.centerSelection();
break;
case ID_SELECTION_CENTER_HORIZONTALLY:
slice.centerSelectionHorizontally();
break;
case ID_SELECTION_CENTER_VERTICALLY:
slice.centerSelectionVertically();
case ID_SELECTION_CENTER:
slice.centerSelection();
break;
case ID_SELECTION_CENTER_HORIZONTALLY:
slice.centerSelectionHorizontally();
break;
case ID_SELECTION_CENTER_VERTICALLY:
slice.centerSelectionVertically();
break;
}
@@ -384,22 +416,23 @@ void ImageSliceWindow::updateControls() {
// ----------------------------------------------------------------------------- : ImageSliceWindow : Event table
BEGIN_EVENT_TABLE(ImageSliceWindow, wxDialog)
EVT_BUTTON (wxID_OK, ImageSliceWindow::onOk)
EVT_RADIOBOX (ID_SIZE, ImageSliceWindow::onChangeSize)
EVT_TEXT (ID_LEFT, ImageSliceWindow::onChangeLeft)
EVT_TEXT (ID_TOP, ImageSliceWindow::onChangeTop)
EVT_TEXT (ID_WIDTH, ImageSliceWindow::onChangeWidth)
EVT_TEXT (ID_HEIGHT, ImageSliceWindow::onChangeHeight)
EVT_BUTTON (ID_SELECTION_CENTER, ImageSliceWindow::onSelectionCenter)
EVT_BUTTON(ID_SELECTION_CENTER_HORIZONTALLY, ImageSliceWindow::onSelectionCenter)
EVT_BUTTON(ID_SELECTION_CENTER_VERTICALLY, ImageSliceWindow::onSelectionCenter)
EVT_CHECKBOX (ID_FIX_ASPECT, ImageSliceWindow::onChangeFixAspect)
EVT_SPINCTRL (ID_ZOOM, ImageSliceWindow::onChangeZoom)
EVT_SPINCTRL (ID_ZOOM_X, ImageSliceWindow::onChangeZoomX)
EVT_SPINCTRL (ID_ZOOM_Y, ImageSliceWindow::onChangeZoomY)
EVT_CHECKBOX (ID_SHARPEN, ImageSliceWindow::onChangeSharpen)
EVT_COMMAND_SCROLL (ID_SHARPEN_AMOUNT, ImageSliceWindow::onChangeSharpenAmount)
EVT_SLICE_CHANGED (wxID_ANY, ImageSliceWindow::onSliceChange)
EVT_BUTTON (wxID_OK, ImageSliceWindow::onOk)
EVT_RADIOBOX (ID_SIZE, ImageSliceWindow::onChangeSize)
EVT_RADIOBOX (ID_GRID, ImageSliceWindow::onChangeGrid)
EVT_TEXT (ID_LEFT, ImageSliceWindow::onChangeLeft)
EVT_TEXT (ID_TOP, ImageSliceWindow::onChangeTop)
EVT_TEXT (ID_WIDTH, ImageSliceWindow::onChangeWidth)
EVT_TEXT (ID_HEIGHT, ImageSliceWindow::onChangeHeight)
EVT_BUTTON (ID_SELECTION_CENTER, ImageSliceWindow::onSelectionCenter)
EVT_BUTTON (ID_SELECTION_CENTER_HORIZONTALLY, ImageSliceWindow::onSelectionCenter)
EVT_BUTTON (ID_SELECTION_CENTER_VERTICALLY, ImageSliceWindow::onSelectionCenter)
EVT_CHECKBOX (ID_FIX_ASPECT, ImageSliceWindow::onChangeFixAspect)
EVT_SPINCTRL (ID_ZOOM, ImageSliceWindow::onChangeZoom)
EVT_SPINCTRL (ID_ZOOM_X, ImageSliceWindow::onChangeZoomX)
EVT_SPINCTRL (ID_ZOOM_Y, ImageSliceWindow::onChangeZoomY)
EVT_CHECKBOX (ID_SHARPEN, ImageSliceWindow::onChangeSharpen)
EVT_COMMAND_SCROLL (ID_SHARPEN_AMOUNT, ImageSliceWindow::onChangeSharpenAmount)
EVT_SLICE_CHANGED (wxID_ANY, ImageSliceWindow::onSliceChange)
// EVT_SIZE ( ImageSliceWindow::onSize)
END_EVENT_TABLE ()
@@ -409,10 +442,11 @@ END_EVENT_TABLE ()
// ----------------------------------------------------------------------------- : ImageSlicePreview
ImageSlicePreview::ImageSlicePreview(Window* parent, int id, ImageSlice& slice, const AlphaMask& mask)
ImageSlicePreview::ImageSlicePreview(Window* parent, int id, ImageSlice& slice, const AlphaMask& mask, const int grid)
: wxControl(parent, id, wxDefaultPosition, wxDefaultSize, wxBORDER_THEME)
, slice(slice)
, mask(mask)
, grid(grid)
, mouse_down(false)
{
SetBackgroundStyle(wxBG_STYLE_PAINT);
@@ -421,22 +455,22 @@ ImageSlicePreview::ImageSlicePreview(Window* parent, int id, ImageSlice& slice,
void ImageSlicePreview::update() {
bitmap = wxNullBitmap;
Refresh(false);
}
}
wxSize ImageSlicePreview::getBestSliceSize() const {
float target_ratio = ((float)slice.target_size.GetWidth()) / ((float)slice.target_size.GetHeight());
if (target_ratio > 1.0) {
return wxSize(500, 500 / target_ratio);
} else {
return wxSize(500 * target_ratio, 500);
if (target_ratio > 1.0) {
return wxSize(500, 500 / target_ratio);
} else {
return wxSize(500 * target_ratio, 500);
}
}
wxSize ImageSlicePreview::DoGetBestSize() const {
// We know the client size we want, calculate the size that goes with that
// We know the client size we want, calculate the size that goes with that
// This helps with applying margins and other spacing necessities.
wxSize ws = GetSize(), cs = GetClientSize();
wxSize ws = GetSize(), cs = GetClientSize();
return getBestSliceSize() + ws - cs;
}
@@ -461,14 +495,47 @@ void ImageSlicePreview::draw(DC& dc) {
mdc.SelectObject(wxNullBitmap);
} else {
bitmap = Bitmap(image);
}
// Rescale the bitmap based on the available size.
auto available_size = getBestSliceSize();
}
// Rescale the bitmap based on the available size.
auto available_size = getBestSliceSize();
bitmap = wxBitmap(bitmap.ConvertToImage().Scale(available_size.GetWidth(), available_size.GetHeight()));
}
if (bitmap.Ok()) {
dc.DrawBitmap(bitmap, 0, 0);
dc.DrawBitmap(bitmap, 0, 0);
if (grid == 1) {
wxSize size = dc.GetSize();
dc.SetPen(*wxRED_PEN);
dc.DrawLine(size.x * 1 / 2, 0, size.x * 1 / 2, size.y);
dc.DrawLine(0, size.y * 1 / 2, size.x, size.y * 1 / 2);
} else if (grid == 2) {
wxSize size = dc.GetSize();
dc.SetPen(*wxRED_PEN);
dc.DrawLine(size.x * 1 / 3, 0, size.x * 1 / 3, size.y);
dc.DrawLine(size.x * 2 / 3, 0, size.x * 2 / 3, size.y);
dc.DrawLine(0, size.y * 1 / 3, size.x, size.y * 1 / 3);
dc.DrawLine(0, size.y * 2 / 3, size.x, size.y * 2 / 3);
} else if (grid == 3) {
wxSize size = dc.GetSize();
dc.SetPen(*wxRED_PEN);
dc.DrawLine(size.x * 1 / 4, 0, size.x * 1 / 4, size.y);
dc.DrawLine(size.x * 2 / 4, 0, size.x * 2 / 4, size.y);
dc.DrawLine(size.x * 3 / 4, 0, size.x * 3 / 4, size.y);
dc.DrawLine(0, size.y * 1 / 4, size.x, size.y * 1 / 4);
dc.DrawLine(0, size.y * 2 / 4, size.x, size.y * 2 / 4);
dc.DrawLine(0, size.y * 3 / 4, size.x, size.y * 3 / 4);
} else if (grid == 4) {
wxSize size = dc.GetSize();
dc.SetPen(*wxRED_PEN);
dc.DrawLine(size.x * 1 / 5, 0, size.x * 1 / 5, size.y);
dc.DrawLine(size.x * 2 / 5, 0, size.x * 2 / 5, size.y);
dc.DrawLine(size.x * 3 / 5, 0, size.x * 3 / 5, size.y);
dc.DrawLine(size.x * 4 / 5, 0, size.x * 4 / 5, size.y);
dc.DrawLine(0, size.y * 1 / 5, size.x, size.y * 1 / 5);
dc.DrawLine(0, size.y * 2 / 5, size.x, size.y * 2 / 5);
dc.DrawLine(0, size.y * 3 / 5, size.x, size.y * 3 / 5);
dc.DrawLine(0, size.y * 4 / 5, size.x, size.y * 4 / 5);
}
}
}
@@ -519,9 +586,9 @@ ImageSliceSelector::ImageSliceSelector(Window* parent, int id, ImageSlice& slice
: wxControl(parent, id, wxDefaultPosition, wxDefaultSize, wxBORDER_THEME)
, slice(slice)
, mouse_down(false)
{
float target_ratio = ((float) slice.source.GetWidth()) / ((float) slice.source.GetHeight());
{
float target_ratio = ((float) slice.source.GetWidth()) / ((float) slice.source.GetHeight());
if (target_ratio > 1.0) {
SetMinSize(wxSize(500, 500 / target_ratio));
} else {