mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
add bleed edge option, get_card_export_settings function
This commit is contained in:
+18
-15
@@ -574,10 +574,10 @@ label:
|
|||||||
dark mode yes: Dark mode
|
dark mode yes: Dark mode
|
||||||
app language: Language of the user interface:
|
app language: Language of the user interface:
|
||||||
card display: Card Display
|
card display: Card Display
|
||||||
storage: Storage
|
|
||||||
zoom: &Zoom:
|
zoom: &Zoom:
|
||||||
export: &Export:
|
import: Import
|
||||||
scale: &Internal Scale:
|
export: &Export
|
||||||
|
scale: Use the following scale:
|
||||||
use export scale: Use Export Scale
|
use export scale: Use Export Scale
|
||||||
export around 300: Around 300 DPI
|
export around 300: Around 300 DPI
|
||||||
export force 300: Force 300 DPI
|
export force 300: Force 300 DPI
|
||||||
@@ -586,10 +586,11 @@ label:
|
|||||||
external programs: External programs
|
external programs: External programs
|
||||||
apprentice: &Apprentice:
|
apprentice: &Apprentice:
|
||||||
apprentice exe: Apprentice Executable
|
apprentice exe: Apprentice Executable
|
||||||
|
export desc: When exporting cards to images:
|
||||||
|
import desc: When importing images for illustrations:
|
||||||
internal scale desc:
|
internal scale desc:
|
||||||
Scale to internally store card images at.
|
Changing the scale does not retroactively apply
|
||||||
Changing this may impact how Sharpening looks.
|
to existing images. You must re-import them.
|
||||||
Does not retroactively apply to existing images.
|
|
||||||
check at startup: Check for new versions at startup
|
check at startup: Check for new versions at startup
|
||||||
checking requires internet:
|
checking requires internet:
|
||||||
Checking for updates requires an internet connection.
|
Checking for updates requires an internet connection.
|
||||||
@@ -741,21 +742,23 @@ button:
|
|||||||
high quality: &High quality rendering
|
high quality: &High quality rendering
|
||||||
show lines: Show &lines around fields
|
show lines: Show &lines around fields
|
||||||
show editing hints: Show boxes and hints for &editing
|
show editing hints: Show boxes and hints for &editing
|
||||||
zoom export:
|
|
||||||
Use Viewer zoom and rotation
|
|
||||||
settings when e&xporting
|
|
||||||
rotation export:
|
rotation export:
|
||||||
Use Viewer rotation
|
Use the card preview
|
||||||
setting when e&xporting
|
rotation setting
|
||||||
|
bleed export:
|
||||||
|
Add a crude print
|
||||||
|
bleed margin
|
||||||
notes export:
|
notes export:
|
||||||
Export card notes inside
|
Add the card notes in
|
||||||
image meta data
|
the image metadata
|
||||||
spellcheck enabled: Show &spelling errors on cards
|
spellcheck enabled: Show &spelling errors on cards
|
||||||
check now: Check &Now
|
check now: Check &Now
|
||||||
always: Always
|
always: Always
|
||||||
if internet connection exists: If internet connection exists
|
if internet connection exists: If internet connection exists
|
||||||
never: Never
|
never: Never
|
||||||
internal image extension: Store images internally with file extension
|
internal image extension:
|
||||||
|
Store images internally
|
||||||
|
with file extension
|
||||||
|
|
||||||
# column select
|
# column select
|
||||||
move up: Move &Up
|
move up: Move &Up
|
||||||
@@ -824,7 +827,7 @@ title:
|
|||||||
global: Global
|
global: Global
|
||||||
display: Display
|
display: Display
|
||||||
directories: Directories
|
directories: Directories
|
||||||
internal: Internal
|
transfers: Transfers
|
||||||
updates: Updates
|
updates: Updates
|
||||||
update check: Update Check
|
update check: Update Check
|
||||||
locate apprentice: Locate Apprentice
|
locate apprentice: Locate Apprentice
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
Function: get_card_export_settings
|
||||||
|
|
||||||
|
--Usage--
|
||||||
|
> get_card_export_settings(card)
|
||||||
|
|
||||||
|
Get the zoom, angle and bleed with which a card is to be exported, as specified by the user in the preferences menu.
|
||||||
|
|
||||||
|
Returns and array whose first element is the zoom percentage, the second is the angle in degrees, and the third is the bleed edge size in pixels.
|
||||||
|
|
||||||
|
--Parameters--
|
||||||
|
! Parameter Type Description
|
||||||
|
| @input@ [[type:card]] The card you want to retrieve the export settings from.
|
||||||
|
| @set@ [[type:set]] The set the card belongs to. This can be omited since "set" is a predefined variable.
|
||||||
@@ -108,6 +108,7 @@ These functions are built into the program, other [[type:function]]s can be defi
|
|||||||
| [[fun:add_card_to_set]] Add a [[type:card]] to a [[type:set]].
|
| [[fun:add_card_to_set]] Add a [[type:card]] to a [[type:set]].
|
||||||
| [[fun:get_card_styling]] Get the styling data of a [[type:card]].
|
| [[fun:get_card_styling]] Get the styling data of a [[type:card]].
|
||||||
| [[fun:get_card_stylesheet]] Get the stylesheet of a [[type:card]].
|
| [[fun:get_card_stylesheet]] Get the stylesheet of a [[type:card]].
|
||||||
|
| [[fun:get_card_export_settings]] Get the zoom, angle and bleed size at which the card will be exported.
|
||||||
| [[fun:get_card_from_uid]] Find the [[type:card]] with the given uid.
|
| [[fun:get_card_from_uid]] Find the [[type:card]] with the given uid.
|
||||||
| [[fun:get_cards_from_link]] Find all [[type:card]]s that have the given link type to the given [[type:card]].
|
| [[fun:get_cards_from_link]] Find all [[type:card]]s that have the given link type to the given [[type:card]].
|
||||||
| [[fun:get_front_face]] Find a [[type:card]] that has the link type "Front Face" to the given [[type:card]].
|
| [[fun:get_front_face]] Find a [[type:card]] that has the link type "Front Face" to the given [[type:card]].
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
Function: write_image_file
|
Function: write_image_file
|
||||||
|
|
||||||
--Usage--
|
--Usage--
|
||||||
> write_image_file(some_image, file: filename)
|
> write_image_file(some_image, file: filename, width: 375, height: 523)
|
||||||
|
> write_image_file(some_card, file: filename, zoom: 1.0, angle: 0.0, bleed: 18.0)
|
||||||
|
|
||||||
Write an image to a file in the output directory.
|
Write a given image, or a given card's image to a file in the output directory.
|
||||||
If a file with the given name already exists it is overwritten.
|
If a file with the given name already exists it is overwritten.
|
||||||
|
|
||||||
Returns the name of the file written.
|
Returns the name of the file written.
|
||||||
@@ -12,10 +13,14 @@ This function can only be used in an [[type:export template]], when <tt>create d
|
|||||||
|
|
||||||
--Parameters--
|
--Parameters--
|
||||||
! Parameter Type Description
|
! Parameter Type Description
|
||||||
| @input@ [[type:image]] Image to write to the file.
|
| @input@ [[type:image]] or [[type:card]] Image or Card to write to the file.
|
||||||
| @file@ [[type:string]] Name of the file to write to
|
| @file@ [[type:string]] Name of the file to write to.
|
||||||
| @width@ [[type:int]] Width in pixels to use for the image, by default the size of the image is used if available.
|
| @width@ [[type:int]] Width in pixels to use for the image, by default the size of the image is used if available.
|
||||||
| @height@ [[type:int]] Height in pixels to use for the image, by default the size of the image is used if available.
|
| @height@ [[type:int]] Height in pixels to use for the image, by default the size of the image is used if available.
|
||||||
|
| @zoom@ [[type:double]] Zoom percentage to apply to the card render.
|
||||||
|
| @angle@ [[type:double]] Angle in degrees to apply to the card render.
|
||||||
|
| @bleed@ [[type:double]] Print bleed margin in pixels to apply to the card render.
|
||||||
|
| @use_user_settings@ [[type:bool]] Use app settings for zoom, angle and bleed instead.
|
||||||
|
|
||||||
--Examples--
|
--Examples--
|
||||||
> write_image_file(file:"image_out.png", linear_blend(...)) == "image_out.png" # image_out.png now contains the given image
|
> write_image_file(file:"image_out.png", linear_blend(...)) == "image_out.png" # image_out.png now contains the given image
|
||||||
|
|||||||
+23
-5
@@ -126,11 +126,29 @@ public:
|
|||||||
inline RealPoint getPos() const { return RealPoint(left, top); }
|
inline RealPoint getPos() const { return RealPoint(left, top); }
|
||||||
inline RealSize getSize() const { return RealSize(width, height); }
|
inline RealSize getSize() const { return RealSize(width, height); }
|
||||||
inline RealRect getExternalRect() const { return RealRect(left, top, width, height); }
|
inline RealRect getExternalRect() const { return RealRect(left, top, width, height); }
|
||||||
inline String getExternalRectString(double scale = 1.0, int offset = 0) { ///< update the style before calling this
|
inline String getExternalRectString(double scale, Radians angle, double bleed, int img_width, int img_height, int img_offset) { ///< update the style before calling this
|
||||||
return _("---") + wxString::Format(wxT("%i"), (int)std::ceil(scale * left + offset)) +
|
double x = left * scale, y = top * scale;
|
||||||
_("-") + wxString::Format(wxT("%i"), (int)std::ceil(scale * top)) +
|
double w = width * scale, h = height * scale;
|
||||||
_("-") + wxString::Format(wxT("%i"), (int)std::floor(scale * width)) +
|
RealRect rect(x, y, w, h);
|
||||||
_("-") + wxString::Format(wxT("%i"), (int)std::floor(scale * height)) +
|
int degrees = 0;
|
||||||
|
if (is_rad0(angle)) {
|
||||||
|
} else if (is_rad180(angle)) {
|
||||||
|
rect = RealRect(img_width - x - w, img_height - y - h, w, h);
|
||||||
|
degrees = 180;
|
||||||
|
} else if (is_rad90(angle)) {
|
||||||
|
rect = RealRect(y, img_height - x - w, h, w);
|
||||||
|
degrees = 90;
|
||||||
|
} else if (is_rad270(angle)) {
|
||||||
|
rect = RealRect(img_width - y - h, x, h, w);
|
||||||
|
degrees = 270;
|
||||||
|
} else {
|
||||||
|
return _("");
|
||||||
|
}
|
||||||
|
return _("---") + wxString::Format(wxT("%i"), (int)std::ceil( rect.x + bleed + img_offset)) +
|
||||||
|
_("-") + wxString::Format(wxT("%i"), (int)std::ceil( rect.y + bleed)) +
|
||||||
|
_("-") + wxString::Format(wxT("%i"), (int)std::floor(rect.width)) +
|
||||||
|
_("-") + wxString::Format(wxT("%i"), (int)std::floor(rect.height)) +
|
||||||
|
_("-") + wxString::Format(wxT("%i"), degrees) +
|
||||||
_("---");
|
_("---");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ CardsOnClipboard::CardsOnClipboard(const SetP& set, const String id, const vecto
|
|||||||
img = export_image(set, cards[0]);
|
img = export_image(set, cards[0]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
img = export_image(set, cards, true, 0, 1.0, 0.0);
|
img = export_image(set, cards);
|
||||||
}
|
}
|
||||||
String temp_path = wxFileName::CreateTempFileName(_("mse")) + _(".png");
|
String temp_path = wxFileName::CreateTempFileName(_("mse")) + _(".png");
|
||||||
img.SaveFile(temp_path, wxBITMAP_TYPE_PNG);
|
img.SaveFile(temp_path, wxBITMAP_TYPE_PNG);
|
||||||
|
|||||||
@@ -88,15 +88,11 @@ FileFormatP mtg_editor_file_format();
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Other ways to export
|
// ----------------------------------------------------------------------------- : Other ways to export
|
||||||
|
|
||||||
/// Generate a wxBitmap of one or more cards
|
|
||||||
Bitmap export_bitmap(const SetP& set, const CardP& card, const double zoom = 1.0, const Radians angle_radians = 0.0);
|
|
||||||
Bitmap export_bitmap(const SetP& set, const vector<CardP>& cards, bool scale_to_lowest_dpi, int padding, const double zoom, const Radians angle_radians, vector<double>& scales_out, vector<int>& offsets_out);
|
|
||||||
|
|
||||||
/// Generate a wxImage of one or more cards
|
/// Generate a wxImage of one or more cards
|
||||||
Image export_image(const SetP& set, const CardP& card, const double zoom = 1.0, const Radians angle_radians = 0.0);
|
Image export_image(const SetP& set, const CardP& card, const bool write_metadata = true, const double zoom = 1.0, const Radians angle_radians = 0.0, const double bleed_pixels = 0.0);
|
||||||
Image export_image(const SetP& set, const vector<CardP>& cards, bool scale_to_lowest_dpi = false, int padding = 0, const double zoom = 1.0, const Radians angle_radians = 0.0);
|
Image export_image(const SetP& set, const vector<CardP>& cards, const int padding = 2, const double global_zoom = 1.0, const bool use_zoom_setting = true, const bool use_rotation_setting = true, const bool use_bleed_setting = false);
|
||||||
|
|
||||||
/// Export the image of one or more cards to a given filename, using the app's zoom and rotation settings
|
/// Export the image of one or more cards to a given filename, using the app's zoom, rotation and bleed settings, and including metadata
|
||||||
void export_image(const SetP& set, const CardP& card, const String& filename);
|
void export_image(const SetP& set, const CardP& card, const String& filename);
|
||||||
void export_image(const SetP& set, const vector<CardP>& cards, const String& path, const String& filename_template, FilenameConflicts conflicts);
|
void export_image(const SetP& set, const vector<CardP>& cards, const String& path, const String& filename_template, FilenameConflicts conflicts);
|
||||||
|
|
||||||
|
|||||||
+227
-139
@@ -20,156 +20,243 @@
|
|||||||
#include <render/card/viewer.hpp>
|
#include <render/card/viewer.hpp>
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Card export
|
class ZoomedUnrotatedDataViewer : public DataViewer {
|
||||||
|
|
||||||
class UnzoomedDataViewer : public DataViewer {
|
|
||||||
public:
|
public:
|
||||||
UnzoomedDataViewer();
|
ZoomedUnrotatedDataViewer(double zoom) : zoom(zoom) {};
|
||||||
UnzoomedDataViewer(double zoom, Radians angle);
|
virtual ~ZoomedUnrotatedDataViewer() {};
|
||||||
virtual ~UnzoomedDataViewer() {};
|
|
||||||
Rotation getRotation() const override;
|
Rotation getRotation() const override;
|
||||||
private:
|
private:
|
||||||
double zoom;
|
double zoom;
|
||||||
double angle;
|
|
||||||
bool declared_values;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
UnzoomedDataViewer::UnzoomedDataViewer()
|
Rotation ZoomedUnrotatedDataViewer::getRotation() const {
|
||||||
: zoom(1.0)
|
return Rotation(0.0, stylesheet->getCardRect(), zoom);
|
||||||
, angle(0.0)
|
|
||||||
, declared_values(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
UnzoomedDataViewer::UnzoomedDataViewer(const double zoom, const Radians angle = 0.0)
|
|
||||||
: zoom(zoom)
|
|
||||||
, angle(angle)
|
|
||||||
, declared_values(true)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Rotation UnzoomedDataViewer::getRotation() const {
|
|
||||||
if (!stylesheet) stylesheet = set->stylesheet;
|
|
||||||
if (declared_values) {
|
|
||||||
return Rotation(angle, stylesheet->getCardRect(), zoom, 1.0, ROTATION_ATTACH_TOP_LEFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
double export_zoom = settings.exportZoomSettingsFor(set->stylesheetFor(card));
|
|
||||||
bool use_viewer_rotation = !settings.stylesheetSettingsFor(set->stylesheetFor(card)).card_normal_export();
|
|
||||||
|
|
||||||
if (use_viewer_rotation) {
|
|
||||||
return Rotation(DataViewer::getRotation().getAngle(), stylesheet->getCardRect(), export_zoom, 1.0, ROTATION_ATTACH_TOP_LEFT);
|
|
||||||
} else {
|
|
||||||
return Rotation(angle, stylesheet->getCardRect(), export_zoom, 1.0, ROTATION_ATTACH_TOP_LEFT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : wxBitmap export
|
|
||||||
|
|
||||||
Bitmap export_bitmap(const SetP& set, const CardP& card, const double zoom, const Radians angle_radians) {
|
|
||||||
if (!set) throw Error(_("no set"));
|
|
||||||
UnzoomedDataViewer viewer = UnzoomedDataViewer(zoom, angle_radians);
|
|
||||||
viewer.setSet(set);
|
|
||||||
viewer.setCard(card);
|
|
||||||
// size of cards
|
|
||||||
RealSize size = viewer.getRotation().getExternalSize();
|
|
||||||
// create bitmap & dc
|
|
||||||
Bitmap bitmap((int)size.width, (int)size.height);
|
|
||||||
if (!bitmap.Ok()) throw InternalError(_("Unable to create bitmap"));
|
|
||||||
wxMemoryDC dc;
|
|
||||||
dc.SelectObject(bitmap);
|
|
||||||
// draw
|
|
||||||
viewer.draw(dc);
|
|
||||||
dc.SelectObject(wxNullBitmap);
|
|
||||||
return bitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bitmap export_bitmap(const SetP& set, const vector<CardP>& cards, bool scale_to_lowest_dpi, int padding, const double zoom, const Radians angle_radians, vector<double>& scales_out, vector<int>& offsets_out) {
|
|
||||||
if (!set) throw Error(_("no set"));
|
|
||||||
vector<Bitmap> bitmaps;
|
|
||||||
int width = 0;
|
|
||||||
int height = 0;
|
|
||||||
double lowest_dpi = 1200.0;
|
|
||||||
if (scale_to_lowest_dpi) {
|
|
||||||
FOR_EACH(card, cards) {
|
|
||||||
lowest_dpi = min(lowest_dpi, set->stylesheetFor(card).card_dpi);
|
|
||||||
}
|
|
||||||
lowest_dpi = max(lowest_dpi, 150.0);
|
|
||||||
}
|
|
||||||
// Draw card bitmaps
|
|
||||||
FOR_EACH(card, cards) {
|
|
||||||
double scale = zoom;
|
|
||||||
if (scale_to_lowest_dpi) {
|
|
||||||
double dpi = max(set->stylesheetFor(card).card_dpi, 150.0);
|
|
||||||
scale *= lowest_dpi / dpi;
|
|
||||||
}
|
|
||||||
scales_out.push_back(scale);
|
|
||||||
UnzoomedDataViewer viewer = UnzoomedDataViewer(scale, angle_radians);
|
|
||||||
viewer.setSet(set);
|
|
||||||
viewer.setCard(card);
|
|
||||||
RealSize size = viewer.getRotation().getExternalSize();
|
|
||||||
Bitmap bitmap((int)size.width, (int)size.height);
|
|
||||||
if (!bitmap.Ok()) throw InternalError(_("Unable to create bitmap"));
|
|
||||||
wxMemoryDC bufferDC;
|
|
||||||
bufferDC.SelectObject(bitmap);
|
|
||||||
clearDC(bufferDC, *wxWHITE_BRUSH);
|
|
||||||
viewer.draw(bufferDC);
|
|
||||||
bufferDC.SelectObject(wxNullBitmap);
|
|
||||||
width += (int)size.width;
|
|
||||||
height = max(height, (int)size.height);
|
|
||||||
bitmaps.push_back(bitmap);
|
|
||||||
}
|
|
||||||
// Draw global bitmap
|
|
||||||
Bitmap global_bitmap(width + (bitmaps.size()-1) * padding, height);
|
|
||||||
if (!global_bitmap.Ok()) throw InternalError(_("Unable to create bitmap"));
|
|
||||||
wxMemoryDC globalDC;
|
|
||||||
globalDC.SelectObject(global_bitmap);
|
|
||||||
clearDC(globalDC, *wxWHITE_BRUSH);
|
|
||||||
int offset = 0;
|
|
||||||
FOR_EACH(bitmap, bitmaps) {
|
|
||||||
offsets_out.push_back(offset);
|
|
||||||
globalDC.SetDeviceOrigin(offset, 0);
|
|
||||||
globalDC.DrawBitmap(bitmap, 0, 0);
|
|
||||||
offset += bitmap.GetWidth() + padding;
|
|
||||||
}
|
|
||||||
globalDC.SelectObject(wxNullBitmap);
|
|
||||||
return global_bitmap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : wxImage export
|
// ----------------------------------------------------------------------------- : wxImage export
|
||||||
|
|
||||||
Image export_image(const SetP& set, const CardP& card, const double zoom, const Radians angle_radians) {
|
Image export_image(const SetP& set, const CardP& card, const bool write_metadata, const double zoom, const Radians angle_radians, const double bleed_pixels) {
|
||||||
Bitmap bitmap = export_bitmap(set, card, zoom, angle_radians);
|
if (!set) throw Error(_("no set"));
|
||||||
|
/// create and zoom
|
||||||
|
ZoomedUnrotatedDataViewer viewer = ZoomedUnrotatedDataViewer(zoom);
|
||||||
|
viewer.setSet(set);
|
||||||
|
viewer.setCard(card);
|
||||||
|
RealSize size = viewer.getRotation().getExternalSize();
|
||||||
|
int bleed = lround(bleed_pixels);
|
||||||
|
Bitmap bitmap((int)size.width + 2 * bleed, (int)size.height + 2 * bleed);
|
||||||
|
if (!bitmap.Ok()) throw InternalError(_("Unable to create bitmap"));
|
||||||
|
wxMemoryDC dc;
|
||||||
|
dc.SelectObject(bitmap);
|
||||||
|
dc.SetDeviceOrigin(bleed, bleed);
|
||||||
|
viewer.draw(dc);
|
||||||
|
dc.SelectObject(wxNullBitmap);
|
||||||
Image img = bitmap.ConvertToImage();
|
Image img = bitmap.ConvertToImage();
|
||||||
String data = _("<mse-data-start>[");
|
|
||||||
IndexMap<FieldP, ValueP>& card_data = card->data;
|
/// rotate
|
||||||
boost::json::object& cardv = mse_to_json(card, set.get());
|
img = rotate_image(img, angle_radians);
|
||||||
boost::json::object& cardv_data = cardv["data"].as_object();
|
int width = img.GetWidth(), height = img.GetHeight();
|
||||||
StyleSheetP stylesheet = set->stylesheetForP(card);
|
|
||||||
if (!settings.stylesheetSettingsFor(*stylesheet).card_notes_export()) cardv["notes"] = "";
|
/// add print bleed edge
|
||||||
for(IndexMap<FieldP, ValueP>::iterator it = card_data.begin() ; it != card_data.end() ; ++it) {
|
if (size.width < 1.0 || size.height < 1.0) {
|
||||||
ImageValue* value = dynamic_cast<ImageValue*>(it->get());
|
queue_message(MESSAGE_ERROR, _("Cannot add bleed edge to empty image"));
|
||||||
if (value && !value->filename.empty()) {
|
}
|
||||||
FieldP field = (*it)->fieldP;
|
else {
|
||||||
StyleP style = stylesheet->card_style.at(field->index);
|
if (!img.HasAlpha()) img.InitAlpha();
|
||||||
if (style) {
|
Byte* pixels = img.GetData();
|
||||||
style->update(set->getContext(card));
|
Byte* alpha = img.GetAlpha();
|
||||||
std::string rect = style->getExternalRectString(zoom, 0).ToStdString();
|
// fill top left corner
|
||||||
cardv_data[field->name.ToStdString()] = rect;
|
int pixel;
|
||||||
|
int x_start = 0;
|
||||||
|
int y_start = 0;
|
||||||
|
int ref = bleed + bleed * width;
|
||||||
|
for (int y = 0; y < bleed; ++y) {
|
||||||
|
for (int x = 0; x < bleed; ++x) {
|
||||||
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
|
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||||
|
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||||
|
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||||
|
alpha[pixel] = alpha[ref];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fill top right corner
|
||||||
|
x_start = width - bleed;
|
||||||
|
y_start = 0;
|
||||||
|
ref = x_start - 1 + bleed * width;
|
||||||
|
for (int y = 0; y < bleed; ++y) {
|
||||||
|
for (int x = 0; x < bleed; ++x) {
|
||||||
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
|
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||||
|
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||||
|
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||||
|
alpha[pixel] = alpha[ref];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fill bottom left corner
|
||||||
|
x_start = 0;
|
||||||
|
y_start = height - bleed;
|
||||||
|
ref = bleed + (y_start - 1) * width;
|
||||||
|
for (int y = 0; y < bleed; ++y) {
|
||||||
|
for (int x = 0; x < bleed; ++x) {
|
||||||
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
|
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||||
|
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||||
|
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||||
|
alpha[pixel] = alpha[ref];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fill bottom right corner
|
||||||
|
x_start = width - bleed;
|
||||||
|
y_start = height - bleed;
|
||||||
|
ref = (x_start - 1) + (y_start - 1) * width;
|
||||||
|
for (int y = 0; y < bleed; ++y) {
|
||||||
|
for (int x = 0; x < bleed; ++x) {
|
||||||
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
|
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||||
|
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||||
|
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||||
|
alpha[pixel] = alpha[ref];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fill left border
|
||||||
|
x_start = 0;
|
||||||
|
y_start = bleed;
|
||||||
|
for (int y = 0; y < height - bleed - bleed; ++y) {
|
||||||
|
ref = bleed + (y_start + y) * width;
|
||||||
|
for (int x = 0; x < bleed; ++x) {
|
||||||
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
|
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||||
|
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||||
|
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||||
|
alpha[pixel] = alpha[ref];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fill top border
|
||||||
|
x_start = bleed;
|
||||||
|
y_start = 0;
|
||||||
|
for (int y = 0; y < bleed; ++y) {
|
||||||
|
for (int x = 0; x < width - bleed - bleed; ++x) {
|
||||||
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
|
ref = x_start + x + bleed * width;
|
||||||
|
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||||
|
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||||
|
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||||
|
alpha[pixel] = alpha[ref];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fill right border
|
||||||
|
x_start = width - bleed;
|
||||||
|
y_start = bleed;
|
||||||
|
for (int y = 0; y < height - bleed - bleed; ++y) {
|
||||||
|
ref = width - bleed - 1 + (y_start + y) * width;
|
||||||
|
for (int x = 0; x < bleed; ++x) {
|
||||||
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
|
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||||
|
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||||
|
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||||
|
alpha[pixel] = alpha[ref];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fill bottom border
|
||||||
|
x_start = bleed;
|
||||||
|
y_start = height - bleed;
|
||||||
|
for (int y = 0; y < bleed; ++y) {
|
||||||
|
for (int x = 0; x < width - bleed - bleed; ++x) {
|
||||||
|
pixel = x_start + x + (y_start + y) * width;
|
||||||
|
ref = x_start + x + (height - bleed - 1) * width;
|
||||||
|
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||||
|
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||||
|
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||||
|
alpha[pixel] = alpha[ref];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data += json_ugly_print(cardv) + _("]<mse-data-end>");
|
|
||||||
img.SetOption(wxIMAGE_OPTION_PNG_DESCRIPTION, data);
|
/// add metadata
|
||||||
|
if (write_metadata) {
|
||||||
|
String metadata = _("<mse-card-data>[");
|
||||||
|
IndexMap<FieldP, ValueP>& card_data = card->data;
|
||||||
|
boost::json::object& cardv = mse_to_json(card, set.get());
|
||||||
|
boost::json::object& cardv_data = cardv["data"].as_object();
|
||||||
|
StyleSheetP stylesheet = set->stylesheetForP(card);
|
||||||
|
if (!settings.stylesheetSettingsFor(*stylesheet).card_notes_export()) cardv["notes"] = "";
|
||||||
|
for(IndexMap<FieldP, ValueP>::iterator it = card_data.begin() ; it != card_data.end() ; ++it) {
|
||||||
|
ImageValue* value = dynamic_cast<ImageValue*>(it->get());
|
||||||
|
if (value && !value->filename.empty()) {
|
||||||
|
FieldP field = (*it)->fieldP;
|
||||||
|
StyleP style = stylesheet->card_style.at(field->index);
|
||||||
|
if (style) {
|
||||||
|
style->update(set->getContext(card));
|
||||||
|
std::string rect = style->getExternalRectString(zoom, angle_radians, bleed_pixels, width, height, 0).ToStdString();
|
||||||
|
cardv_data[field->name.ToStdString()] = rect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metadata += json_ugly_print(cardv) + _("]</mse-card-data>");
|
||||||
|
img.SetOption(wxIMAGE_OPTION_PNG_DESCRIPTION, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image export_image(const SetP& set, const vector<CardP>& cards, bool scale_to_lowest_dpi, int padding, const double zoom, const Radians angle_radians) {
|
Image export_image( const SetP& set, const vector<CardP>& cards,
|
||||||
vector<double> scales;
|
const int padding,
|
||||||
|
const double global_zoom,
|
||||||
|
const bool use_zoom_setting,
|
||||||
|
const bool use_rotation_setting,
|
||||||
|
const bool use_bleed_setting) {
|
||||||
|
if (!set) throw Error(_("no set"));
|
||||||
|
if (cards.size() == 0) throw Error(_("no cards"));
|
||||||
|
vector<Image> imgs;
|
||||||
vector<int> offsets;
|
vector<int> offsets;
|
||||||
Bitmap bitmap = export_bitmap(set, cards, scale_to_lowest_dpi, padding, zoom, angle_radians, scales, offsets);
|
vector<double> zooms;
|
||||||
Image img = bitmap.ConvertToImage();
|
vector<double> angles;
|
||||||
String data = _("<mse-data-start>[");
|
vector<double> bleeds;
|
||||||
|
// Draw card images
|
||||||
|
FOR_EACH(card, cards) {
|
||||||
|
Settings::ExportSettings card_settings = settings.exportSettingsFor(set->stylesheetFor(card));
|
||||||
|
double zoom = use_zoom_setting ? global_zoom * card_settings.zoom : global_zoom;
|
||||||
|
double angle = use_rotation_setting ? card_settings.angle_radians : 0.0;
|
||||||
|
double bleed = use_bleed_setting ? card_settings.bleed_pixels : 0.0;
|
||||||
|
imgs.push_back(export_image(set, card, false, zoom, angle, bleed));
|
||||||
|
zooms.push_back(zoom);
|
||||||
|
angles.push_back(angle);
|
||||||
|
bleeds.push_back(bleed);
|
||||||
|
}
|
||||||
|
int global_width = 0;
|
||||||
|
int global_height = 0;
|
||||||
|
vector<int> widths;
|
||||||
|
vector<int> heights;
|
||||||
|
FOR_EACH(img, imgs) {
|
||||||
|
int width = img.GetWidth();
|
||||||
|
int height = img.GetHeight();
|
||||||
|
widths.push_back(width);
|
||||||
|
heights.push_back(height);
|
||||||
|
offsets.push_back(global_width);
|
||||||
|
global_width += padding + width;
|
||||||
|
global_height = max(global_height, height);
|
||||||
|
}
|
||||||
|
global_width -= padding;
|
||||||
|
// Draw global image
|
||||||
|
Image global_img = Image(global_width, global_height);
|
||||||
|
if (!global_img.Ok()) throw InternalError(_("Unable to create image"));
|
||||||
|
global_img.InitAlpha();
|
||||||
|
Byte* pixels = global_img.GetData();
|
||||||
|
Byte* alpha = global_img.GetAlpha();
|
||||||
|
// fill with transparent
|
||||||
|
for (UInt i = 0; i < global_width*global_height; ++i) {
|
||||||
|
pixels[3 * i + 0] = 0;
|
||||||
|
pixels[3 * i + 1] = 0;
|
||||||
|
pixels[3 * i + 2] = 0;
|
||||||
|
alpha[i] = 0;
|
||||||
|
}
|
||||||
|
// Paste card images
|
||||||
|
FOR_EACH_2(img, imgs, offset, offsets) {
|
||||||
|
global_img.Paste(img, offset, 0);
|
||||||
|
}
|
||||||
|
// Write metadata
|
||||||
|
String metadata = _("<mse-card-data>[");
|
||||||
for (int i = 0; i < cards.size(); ++i) {
|
for (int i = 0; i < cards.size(); ++i) {
|
||||||
if (i > 0) data += _(",");
|
if (i > 0) metadata += _(",");
|
||||||
CardP card = cards[i];
|
CardP card = cards[i];
|
||||||
IndexMap<FieldP, ValueP>& card_data = card->data;
|
IndexMap<FieldP, ValueP>& card_data = card->data;
|
||||||
boost::json::object& cardv = mse_to_json(card, set.get());
|
boost::json::object& cardv = mse_to_json(card, set.get());
|
||||||
@@ -183,24 +270,25 @@ Image export_image(const SetP& set, const vector<CardP>& cards, bool scale_to_lo
|
|||||||
StyleP style = stylesheet->card_style.at(field->index);
|
StyleP style = stylesheet->card_style.at(field->index);
|
||||||
if (style) {
|
if (style) {
|
||||||
style->update(set->getContext(card));
|
style->update(set->getContext(card));
|
||||||
std::string rect = style->getExternalRectString(scales[i], offsets[i]).ToStdString();
|
Rotation rotation();
|
||||||
|
std::string rect = style->getExternalRectString(zooms[i], angles[i], bleeds[i], widths[i], heights[i], offsets[i]).ToStdString();
|
||||||
cardv_data[field->name.ToStdString()] = rect;
|
cardv_data[field->name.ToStdString()] = rect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data += json_ugly_print(cardv);
|
metadata += json_ugly_print(cardv);
|
||||||
}
|
}
|
||||||
data += _("]<mse-data-end>");
|
metadata += _("]</mse-card-data>");
|
||||||
img.SetOption(wxIMAGE_OPTION_PNG_DESCRIPTION, data);
|
global_img.SetOption(wxIMAGE_OPTION_PNG_DESCRIPTION, metadata);
|
||||||
return img;
|
|
||||||
|
return global_img;
|
||||||
}
|
}
|
||||||
|
|
||||||
void export_image(const SetP& set, const CardP& card, const String& filename) {
|
void export_image(const SetP& set, const CardP& card, const String& filename) {
|
||||||
const StyleSheet& stylesheet = set->stylesheetFor(card);
|
const StyleSheet& stylesheet = set->stylesheetFor(card);
|
||||||
StyleSheetSettings& stylesheet_settings = settings.stylesheetSettingsFor(stylesheet);
|
StyleSheetSettings& stylesheet_settings = settings.stylesheetSettingsFor(stylesheet);
|
||||||
double zoom = settings.exportZoomSettingsFor(stylesheet);
|
Settings::ExportSettings export_settings = settings.exportSettingsFor(stylesheet);
|
||||||
Radians angle = stylesheet_settings.card_normal_export() ? 0.0 : deg_to_rad(stylesheet_settings.card_angle());
|
Image img = export_image(set, card, true, export_settings.zoom, export_settings.angle_radians, export_settings.bleed_pixels);
|
||||||
Image img = export_image(set, card, zoom, angle);
|
|
||||||
img.SaveFile(filename);
|
img.SaveFile(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+73
-60
@@ -32,8 +32,8 @@ IMPLEMENT_REFLECTION_ENUM(CheckUpdates) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IMPLEMENT_REFLECTION_ENUM(InstallType) {
|
IMPLEMENT_REFLECTION_ENUM(InstallType) {
|
||||||
VALUE_N("default", INSTALL_DEFAULT); //default
|
VALUE_N("default", INSTALL_DEFAULT); //default
|
||||||
VALUE_N("local", INSTALL_LOCAL);
|
VALUE_N("local", INSTALL_LOCAL);
|
||||||
VALUE_N("global", INSTALL_GLOBAL);
|
VALUE_N("global", INSTALL_GLOBAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,13 +47,13 @@ bool is_install_local(InstallType type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IMPLEMENT_REFLECTION_ENUM(FilenameConflicts) {
|
IMPLEMENT_REFLECTION_ENUM(FilenameConflicts) {
|
||||||
VALUE_N("keep old", CONFLICT_KEEP_OLD);
|
VALUE_N("keep old", CONFLICT_KEEP_OLD);
|
||||||
VALUE_N("overwrite", CONFLICT_OVERWRITE);
|
VALUE_N("overwrite", CONFLICT_OVERWRITE);
|
||||||
VALUE_N("number", CONFLICT_NUMBER);
|
VALUE_N("number", CONFLICT_NUMBER);
|
||||||
VALUE_N("number overwrite", CONFLICT_NUMBER_OVERWRITE);
|
VALUE_N("number overwrite", CONFLICT_NUMBER_OVERWRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
const vector<int> Settings::export_zoom_choices = { 50,66,75,80,100,120,125,150,175,200 };
|
const vector<int> Settings::scale_choices = { 50,66,75,80,100,120,125,150,175,200 };
|
||||||
|
|
||||||
const int COLUMN_NOT_INITIALIZED = -100000;
|
const int COLUMN_NOT_INITIALIZED = -100000;
|
||||||
|
|
||||||
@@ -71,13 +71,13 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(ColumnSettings) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GameSettings::GameSettings()
|
GameSettings::GameSettings()
|
||||||
: sort_cards_ascending(true)
|
: sort_cards_ascending (true)
|
||||||
, images_export_filename(_("{card.name}.png"))
|
, images_export_filename (_("{card.name}.png"))
|
||||||
, images_export_conflicts(CONFLICT_NUMBER_OVERWRITE)
|
, images_export_conflicts (CONFLICT_NUMBER_OVERWRITE)
|
||||||
, use_auto_replace(true)
|
, use_auto_replace (true)
|
||||||
, pack_seed_random(true)
|
, pack_seed_random (true)
|
||||||
, pack_seed(123456)
|
, pack_seed (123456)
|
||||||
, initialized(false)
|
, initialized (false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void GameSettings::initDefaults(const Game& game) {
|
void GameSettings::initDefaults(const Game& game) {
|
||||||
@@ -128,37 +128,40 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(GameSettings) {
|
|||||||
|
|
||||||
|
|
||||||
StyleSheetSettings::StyleSheetSettings()
|
StyleSheetSettings::StyleSheetSettings()
|
||||||
: card_zoom (1.0, true)
|
: card_zoom (1.0, true)
|
||||||
, export_zoom_selection (0, true)
|
, export_scale_selection (0, true)
|
||||||
, card_angle (0, true)
|
, card_angle (0, true)
|
||||||
, card_anti_alias (true, true)
|
, card_anti_alias (true, true)
|
||||||
, card_borders (true, true)
|
, card_borders (true, true)
|
||||||
, card_draw_editing (true, true)
|
, card_draw_editing (true, true)
|
||||||
, card_normal_export (true, true)
|
, card_normal_export (true, true)
|
||||||
, card_notes_export (false, true)
|
, card_bleed_export (false, true)
|
||||||
, card_spellcheck_enabled(true, true)
|
, card_notes_export (false, true)
|
||||||
|
, card_spellcheck_enabled (true, true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void StyleSheetSettings::useDefault(const StyleSheetSettings& ss) {
|
void StyleSheetSettings::useDefault(const StyleSheetSettings& ss) {
|
||||||
if (card_zoom .isDefault()) card_zoom .assignDefault(ss.card_zoom);
|
if (card_zoom .isDefault()) card_zoom .assignDefault(ss.card_zoom);
|
||||||
if (export_zoom_selection .isDefault()) export_zoom_selection .assignDefault(ss.export_zoom_selection);
|
if (export_scale_selection .isDefault()) export_scale_selection .assignDefault(ss.export_scale_selection);
|
||||||
if (card_angle .isDefault()) card_angle .assignDefault(ss.card_angle);
|
if (card_angle .isDefault()) card_angle .assignDefault(ss.card_angle);
|
||||||
if (card_anti_alias .isDefault()) card_anti_alias .assignDefault(ss.card_anti_alias);
|
if (card_anti_alias .isDefault()) card_anti_alias .assignDefault(ss.card_anti_alias);
|
||||||
if (card_borders .isDefault()) card_borders .assignDefault(ss.card_borders);
|
if (card_borders .isDefault()) card_borders .assignDefault(ss.card_borders);
|
||||||
if (card_draw_editing .isDefault()) card_draw_editing .assignDefault(ss.card_draw_editing);
|
if (card_draw_editing .isDefault()) card_draw_editing .assignDefault(ss.card_draw_editing);
|
||||||
if (card_normal_export .isDefault()) card_normal_export .assignDefault(ss.card_normal_export);
|
if (card_normal_export .isDefault()) card_normal_export .assignDefault(ss.card_normal_export);
|
||||||
|
if (card_bleed_export .isDefault()) card_bleed_export .assignDefault(ss.card_bleed_export);
|
||||||
if (card_notes_export .isDefault()) card_notes_export .assignDefault(ss.card_notes_export);
|
if (card_notes_export .isDefault()) card_notes_export .assignDefault(ss.card_notes_export);
|
||||||
if (card_spellcheck_enabled.isDefault()) card_spellcheck_enabled.assignDefault(ss.card_spellcheck_enabled);
|
if (card_spellcheck_enabled.isDefault()) card_spellcheck_enabled.assignDefault(ss.card_spellcheck_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPLEMENT_REFLECTION_NO_SCRIPT(StyleSheetSettings) {
|
IMPLEMENT_REFLECTION_NO_SCRIPT(StyleSheetSettings) {
|
||||||
REFLECT(card_zoom);
|
REFLECT(card_zoom);
|
||||||
REFLECT(export_zoom_selection);
|
REFLECT(export_scale_selection);
|
||||||
REFLECT(card_angle);
|
REFLECT(card_angle);
|
||||||
REFLECT(card_anti_alias);
|
REFLECT(card_anti_alias);
|
||||||
REFLECT(card_borders);
|
REFLECT(card_borders);
|
||||||
REFLECT(card_draw_editing);
|
REFLECT(card_draw_editing);
|
||||||
REFLECT(card_normal_export);
|
REFLECT(card_normal_export);
|
||||||
|
REFLECT(card_bleed_export);
|
||||||
REFLECT(card_notes_export);
|
REFLECT(card_notes_export);
|
||||||
REFLECT(card_spellcheck_enabled);
|
REFLECT(card_spellcheck_enabled);
|
||||||
}
|
}
|
||||||
@@ -184,29 +187,29 @@ IMPLEMENT_REFLECTION_ENUM(DarkModeType) {
|
|||||||
Settings settings;
|
Settings settings;
|
||||||
|
|
||||||
Settings::Settings()
|
Settings::Settings()
|
||||||
: locale (_("en"))
|
: locale (_("en"))
|
||||||
, set_window_maximized (false)
|
, set_window_maximized (false)
|
||||||
, set_window_width (790)
|
, set_window_width (790)
|
||||||
, set_window_height (300)
|
, set_window_height (300)
|
||||||
, card_notes_height (40)
|
, card_notes_height (40)
|
||||||
, open_sets_in_new_window (true)
|
, open_sets_in_new_window (true)
|
||||||
, symbol_grid_size (30)
|
, symbol_grid_size (30)
|
||||||
, symbol_grid (true)
|
, symbol_grid (true)
|
||||||
, symbol_grid_snap (false)
|
, symbol_grid_snap (false)
|
||||||
, print_spacing (0.33)
|
, print_spacing (0.33)
|
||||||
, print_cutter_lines (CUTTER_ALL)
|
, print_cutter_lines (CUTTER_ALL)
|
||||||
, dark_mode_type (DARKMODE_SYSTEM)
|
, dark_mode_type (DARKMODE_SYSTEM)
|
||||||
, internal_scale_selection(0)
|
, import_scale_selection (0)
|
||||||
, internal_image_extension(true)
|
, internal_image_extension (true)
|
||||||
#if USE_OLD_STYLE_UPDATE_CHECKER
|
#if USE_OLD_STYLE_UPDATE_CHECKER
|
||||||
, updates_url (_("https://magicseteditor.boards.net/page/downloads"))
|
, updates_url (_("https://magicseteditor.boards.net/page/downloads"))
|
||||||
#endif
|
#endif
|
||||||
, package_versions_url (_("https://magicseteditor.boards.net/page/downloads"))
|
, package_versions_url (_("https://magicseteditor.boards.net/page/downloads"))
|
||||||
, installer_list_url (_("https://magicseteditor.boards.net/page/downloads"))
|
, installer_list_url (_("https://magicseteditor.boards.net/page/downloads"))
|
||||||
, check_updates (CHECK_IF_CONNECTED)
|
, check_updates (CHECK_IF_CONNECTED)
|
||||||
, check_updates_all (true)
|
, check_updates_all (true)
|
||||||
, website_url (_("https://magicseteditor.boards.net/"))
|
, website_url (_("https://magicseteditor.boards.net/"))
|
||||||
, install_type (INSTALL_DEFAULT)
|
, install_type (INSTALL_DEFAULT)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void Settings::addRecentFile(const String& filename) {
|
void Settings::addRecentFile(const String& filename) {
|
||||||
@@ -231,6 +234,7 @@ GameSettings& Settings::gameSettingsFor(const Game& game) {
|
|||||||
gs->initDefaults(game);
|
gs->initDefaults(game);
|
||||||
return *gs;
|
return *gs;
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnSettings& Settings::columnSettingsFor(const Game& game, const Field& field) {
|
ColumnSettings& Settings::columnSettingsFor(const Game& game, const Field& field) {
|
||||||
// Get game info
|
// Get game info
|
||||||
GameSettings& gs = gameSettingsFor(game);
|
GameSettings& gs = gameSettingsFor(game);
|
||||||
@@ -244,6 +248,7 @@ ColumnSettings& Settings::columnSettingsFor(const Game& game, const Field& field
|
|||||||
}
|
}
|
||||||
return cs;
|
return cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
StyleSheetSettings& Settings::stylesheetSettingsFor(const StyleSheet& stylesheet) {
|
StyleSheetSettings& Settings::stylesheetSettingsFor(const StyleSheet& stylesheet) {
|
||||||
// Use the canonical form here since the stylesheet name will be used as a stored key.
|
// Use the canonical form here since the stylesheet name will be used as a stored key.
|
||||||
// This does introduce the possibility of collision if two stylesheets return the same value canonically, but I think that's just a necessary risk.
|
// This does introduce the possibility of collision if two stylesheets return the same value canonically, but I think that's just a necessary risk.
|
||||||
@@ -253,28 +258,36 @@ StyleSheetSettings& Settings::stylesheetSettingsFor(const StyleSheet& stylesheet
|
|||||||
return *ss;
|
return *ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Settings::exportZoomSettingsFor(const StyleSheet& stylesheet) {
|
double Settings::exportScaleSettingsFor(const StyleSheet& stylesheet) {
|
||||||
StyleSheetSettings& ss = stylesheetSettingsFor(stylesheet);
|
StyleSheetSettings& ss = stylesheetSettingsFor(stylesheet);
|
||||||
int export_zoom = ss.export_zoom_selection();
|
int export_scale = ss.export_scale_selection();
|
||||||
if (export_zoom == 0) return adaptiveZoomSettingsFor(stylesheet, 300.0, 50.0);
|
if (export_scale == 0) return adaptiveScaleSettingsFor(stylesheet, 300.0, 50.0);
|
||||||
if (export_zoom == 1) return adaptiveZoomSettingsFor(stylesheet, 300.0, 1.0);
|
if (export_scale == 1) return adaptiveScaleSettingsFor(stylesheet, 300.0, 1.0);
|
||||||
if (export_zoom == 2) return adaptiveZoomSettingsFor(stylesheet, 150.0, 1.0);
|
if (export_scale == 2) return adaptiveScaleSettingsFor(stylesheet, 150.0, 1.0);
|
||||||
return export_zoom_choices[export_zoom - 3] / 100;
|
return scale_choices[export_scale - 3] / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Settings::internalScaleSettingsFor(const StyleSheet& stylesheet) {
|
double Settings::importScaleSettingsFor(const StyleSheet& stylesheet) {
|
||||||
if (internal_scale_selection == 0) return exportZoomSettingsFor(stylesheet);
|
if (import_scale_selection == 0) return exportScaleSettingsFor(stylesheet);
|
||||||
if (internal_scale_selection == 1) return adaptiveZoomSettingsFor(stylesheet, 300.0, 50.0);
|
if (import_scale_selection == 1) return adaptiveScaleSettingsFor(stylesheet, 300.0, 50.0);
|
||||||
if (internal_scale_selection == 2) return adaptiveZoomSettingsFor(stylesheet, 300.0, 1.0);
|
if (import_scale_selection == 2) return adaptiveScaleSettingsFor(stylesheet, 300.0, 1.0);
|
||||||
if (internal_scale_selection == 3) return adaptiveZoomSettingsFor(stylesheet, 150.0, 1.0);
|
if (import_scale_selection == 3) return adaptiveScaleSettingsFor(stylesheet, 150.0, 1.0);
|
||||||
return export_zoom_choices[internal_scale_selection - 4] / 100;
|
return scale_choices[import_scale_selection - 4] / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Settings::adaptiveZoomSettingsFor(const StyleSheet& stylesheet, double dpi_target, double dpi_leeway) {
|
double Settings::adaptiveScaleSettingsFor(const StyleSheet& stylesheet, double dpi_target, double dpi_leeway) {
|
||||||
if (abs(stylesheet.card_dpi - dpi_target) <= dpi_leeway) return 1.0;
|
if (abs(stylesheet.card_dpi - dpi_target) <= dpi_leeway) return 1.0;
|
||||||
return dpi_target / max(10.0, stylesheet.card_dpi);
|
return dpi_target / max(10.0, stylesheet.card_dpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Settings::ExportSettings Settings::exportSettingsFor(const StyleSheet& stylesheet) {
|
||||||
|
StyleSheetSettings& ss = stylesheetSettingsFor(stylesheet);
|
||||||
|
double zoom = settings.exportScaleSettingsFor(stylesheet);
|
||||||
|
double angle = ss.card_normal_export() ? 0.0 : deg_to_rad(ss.card_angle());
|
||||||
|
double bleed = ss.card_bleed_export() ? (stylesheet.card_dpi / 300.0) * 36.0 * zoom : 0.0; // 36 pixels of bleed on a 300 DPI print
|
||||||
|
return ExportSettings{zoom, angle, bleed};
|
||||||
|
}
|
||||||
|
|
||||||
IndexMap<FieldP,ValueP>& Settings::exportOptionsFor(const ExportTemplate& export_template) {
|
IndexMap<FieldP,ValueP>& Settings::exportOptionsFor(const ExportTemplate& export_template) {
|
||||||
return export_options.get(export_template.name(), export_template.option_fields);
|
return export_options.get(export_template.name(), export_template.option_fields);
|
||||||
}
|
}
|
||||||
@@ -324,7 +337,7 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(Settings) {
|
|||||||
REFLECT(print_cutter_lines);
|
REFLECT(print_cutter_lines);
|
||||||
REFLECT(dark_mode_type);
|
REFLECT(dark_mode_type);
|
||||||
REFLECT(apprentice_location);
|
REFLECT(apprentice_location);
|
||||||
REFLECT(internal_scale_selection);
|
REFLECT(import_scale_selection);
|
||||||
REFLECT(internal_image_extension);
|
REFLECT(internal_image_extension);
|
||||||
#if USE_OLD_STYLE_UPDATE_CHECKER
|
#if USE_OLD_STYLE_UPDATE_CHECKER
|
||||||
REFLECT(updates_url);
|
REFLECT(updates_url);
|
||||||
|
|||||||
+18
-12
@@ -98,12 +98,13 @@ public:
|
|||||||
|
|
||||||
// Rendering/display settings
|
// Rendering/display settings
|
||||||
Defaultable<double> card_zoom;
|
Defaultable<double> card_zoom;
|
||||||
Defaultable<int> export_zoom_selection;
|
Defaultable<int> export_scale_selection;
|
||||||
Defaultable<Degrees> card_angle;
|
Defaultable<Degrees> card_angle;
|
||||||
Defaultable<bool> card_anti_alias;
|
Defaultable<bool> card_anti_alias;
|
||||||
Defaultable<bool> card_borders;
|
Defaultable<bool> card_borders;
|
||||||
Defaultable<bool> card_draw_editing;
|
Defaultable<bool> card_draw_editing;
|
||||||
Defaultable<bool> card_normal_export;
|
Defaultable<bool> card_normal_export;
|
||||||
|
Defaultable<bool> card_bleed_export;
|
||||||
Defaultable<bool> card_notes_export;
|
Defaultable<bool> card_notes_export;
|
||||||
Defaultable<bool> card_spellcheck_enabled;
|
Defaultable<bool> card_spellcheck_enabled;
|
||||||
|
|
||||||
@@ -174,17 +175,22 @@ public:
|
|||||||
|
|
||||||
// --------------------------------------------------- : Game/stylesheet specific
|
// --------------------------------------------------- : Game/stylesheet specific
|
||||||
|
|
||||||
/// Get the settings object for a specific game
|
struct ExportSettings {
|
||||||
GameSettings& gameSettingsFor (const Game& game);
|
double zoom, angle_radians, bleed_pixels;
|
||||||
/// Get the settings for a column for a specific field in a game
|
};
|
||||||
ColumnSettings& columnSettingsFor (const Game& game, const Field& field);
|
|
||||||
/// Get the settings object for a specific stylesheet
|
|
||||||
StyleSheetSettings& stylesheetSettingsFor (const StyleSheet& stylesheet);
|
|
||||||
double exportZoomSettingsFor (const StyleSheet& stylesheet);
|
|
||||||
double internalScaleSettingsFor(const StyleSheet& stylesheet);
|
|
||||||
double adaptiveZoomSettingsFor (const StyleSheet& stylesheet, double target_dpi, double leeway_dpi);
|
|
||||||
|
|
||||||
static const vector<int> export_zoom_choices;
|
/// Get the settings object for a specific game
|
||||||
|
GameSettings& gameSettingsFor (const Game& game);
|
||||||
|
/// Get the settings for a column for a specific field in a game
|
||||||
|
ColumnSettings& columnSettingsFor (const Game& game, const Field& field);
|
||||||
|
/// Get the settings object for a specific stylesheet
|
||||||
|
StyleSheetSettings& stylesheetSettingsFor (const StyleSheet& stylesheet);
|
||||||
|
double exportScaleSettingsFor (const StyleSheet& stylesheet);
|
||||||
|
double importScaleSettingsFor (const StyleSheet& stylesheet);
|
||||||
|
double adaptiveScaleSettingsFor (const StyleSheet& stylesheet, double target_dpi, double leeway_dpi);
|
||||||
|
ExportSettings exportSettingsFor (const StyleSheet& stylesheet);
|
||||||
|
|
||||||
|
static const vector<int> scale_choices;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
map<String,GameSettingsP> game_settings;
|
map<String,GameSettingsP> game_settings;
|
||||||
@@ -221,7 +227,7 @@ public:
|
|||||||
|
|
||||||
// --------------------------------------------------- : Internal settings
|
// --------------------------------------------------- : Internal settings
|
||||||
|
|
||||||
int internal_scale_selection;
|
int import_scale_selection;
|
||||||
bool internal_image_extension;
|
bool internal_image_extension;
|
||||||
|
|
||||||
// --------------------------------------------------- : Update checking
|
// --------------------------------------------------- : Update checking
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
/// Resample (resize) an image, uses bilenear filtering
|
/// Resample (resize) an image, uses bilenear filtering
|
||||||
void resample(const Image& img_in, Image& img_out);
|
void resample(const Image& img_in, Image& img_out);
|
||||||
Image resample(const Image& img_in, int width, int height);
|
Image resample(const Image& img_in, int width, int height);
|
||||||
|
Image resample(const Image& img_in, double zoom);
|
||||||
|
|
||||||
/// Resamples an image, first clips the input image to a specified rectangle
|
/// Resamples an image, first clips the input image to a specified rectangle
|
||||||
/** The selected rectangle is resampled into the entire output image */
|
/** The selected rectangle is resampled into the entire output image */
|
||||||
|
|||||||
@@ -134,6 +134,9 @@ Image resample(const Image& img_in, int width, int height) {
|
|||||||
return img_out;
|
return img_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Image resample(const Image& img_in, double zoom) {
|
||||||
|
return resample(img_in, (int)(img_in.GetWidth() * zoom), (int)(img_in.GetHeight() * zoom));
|
||||||
|
}
|
||||||
|
|
||||||
void resample_and_clip(const Image& img_in, Image& img_out, wxRect rect) {
|
void resample_and_clip(const Image& img_in, Image& img_out, wxRect rect) {
|
||||||
// mask to alpha
|
// mask to alpha
|
||||||
|
|||||||
@@ -303,9 +303,12 @@ bool CardListBase::parseImage(Image& image, vector<CardP>& out) {
|
|||||||
for (IndexMap<FieldP, ValueP>::iterator it = card->data.begin(); it != card->data.end(); it++) {
|
for (IndexMap<FieldP, ValueP>::iterator it = card->data.begin(); it != card->data.end(); it++) {
|
||||||
ImageValue* value = dynamic_cast<ImageValue*>(it->get());
|
ImageValue* value = dynamic_cast<ImageValue*>(it->get());
|
||||||
if (value && !value->filename.empty()) {
|
if (value && !value->filename.empty()) {
|
||||||
wxRect rect = value->filename.getExternalRect();
|
wxRect rect = wxRect(0,0,0,0);
|
||||||
|
int degrees = 0;
|
||||||
|
value->filename.getExternalRect(rect, degrees);
|
||||||
if (rect.width > 0 && rect.height > 0) {
|
if (rect.width > 0 && rect.height > 0) {
|
||||||
Image& img = image.GetSubImage(rect);
|
Image& img = image.GetSubImage(rect);
|
||||||
|
img = rotate_image(img, deg_to_rad(360-degrees));
|
||||||
LocalFileName filename = set->newFileName((*it)->fieldP->name, settings.internal_image_extension ? _(".png") : _("")); // a new unique name in the package
|
LocalFileName filename = set->newFileName((*it)->fieldP->name, settings.internal_image_extension ? _(".png") : _("")); // a new unique name in the package
|
||||||
img.SaveFile(set->nameOut(filename), wxBITMAP_TYPE_PNG);
|
img.SaveFile(set->nameOut(filename), wxBITMAP_TYPE_PNG);
|
||||||
value->filename = filename;
|
value->filename = filename;
|
||||||
@@ -319,8 +322,8 @@ bool CardListBase::parseImage(Image& image, vector<CardP>& out) {
|
|||||||
|
|
||||||
bool CardListBase::parseText(String& text, vector<CardP>& out) {
|
bool CardListBase::parseText(String& text, vector<CardP>& out) {
|
||||||
size_t j = out.size();
|
size_t j = out.size();
|
||||||
if (size_t pos = text.find("<mse-data-start>") != wxString::npos) {
|
if (size_t pos = text.find("<mse-card-data>") != wxString::npos) {
|
||||||
text = text.substr(pos + 15, text.find("<mse-data-end>") - pos - 15);
|
text = text.substr(pos + 14, text.find("</mse-card-data>") - pos - 14);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ScriptValueP& sv = json_to_mse(text, set.get());
|
ScriptValueP& sv = json_to_mse(text, set.get());
|
||||||
|
|||||||
@@ -71,13 +71,12 @@ void ImageSlice::centerSelectionVertically() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Image ImageSlice::getSlice(double scale) const {
|
Image ImageSlice::getSlice() const {
|
||||||
wxSize scaled_target_size = target_size * scale;
|
if (selection.width == target_size.GetWidth() && selection.height == target_size.GetHeight() && selection.x == 0 && selection.y == 0) {
|
||||||
if (selection.width == scaled_target_size.GetWidth() && selection.height == scaled_target_size.GetHeight() && selection.x == 0 && selection.y == 0) {
|
|
||||||
// exactly the right size
|
// exactly the right size
|
||||||
return source.GetSubImage(selection);
|
return source.GetSubImage(selection);
|
||||||
}
|
}
|
||||||
Image target(scaled_target_size.GetWidth(), scaled_target_size.GetHeight(), false);
|
Image target(target_size.GetWidth(), target_size.GetHeight(), false);
|
||||||
if (sharpen && sharpen_amount > 0 && sharpen_amount <= 100) {
|
if (sharpen && sharpen_amount > 0 && sharpen_amount <= 100) {
|
||||||
sharp_resample_and_clip(source, target, selection, sharpen_amount);
|
sharp_resample_and_clip(source, target, selection, sharpen_amount);
|
||||||
} else {
|
} else {
|
||||||
@@ -104,7 +103,6 @@ ImageSliceWindow::ImageSliceWindow(Window* parent, const Image& source, const St
|
|||||||
// init slice
|
// init slice
|
||||||
pair<String, String> settings_entry = { filename, cardname };
|
pair<String, String> settings_entry = { filename, cardname };
|
||||||
if (previously_used_settings_value.find(settings_entry) != previously_used_settings_value.end()) {
|
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.aspect_fixed = false;
|
||||||
slice.sharpen = true;
|
slice.sharpen = true;
|
||||||
slice.sharpen_amount = previously_used_settings_value[settings_entry].second;
|
slice.sharpen_amount = previously_used_settings_value[settings_entry].second;
|
||||||
@@ -242,8 +240,8 @@ void ImageSliceWindow::onOk(wxCommandEvent&) {
|
|||||||
EndModal(wxID_OK);
|
EndModal(wxID_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image ImageSliceWindow::getImage(double scale) const {
|
Image ImageSliceWindow::getImage() const {
|
||||||
Image img = slice.getSlice(scale);
|
Image img = slice.getSlice();
|
||||||
previously_used_settings_path[slice.card_name] = slice.source_path;
|
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 };
|
previously_used_settings_value[{ slice.source_path, slice.card_name }] = { slice.selection, slice.sharpen_amount };
|
||||||
return img;
|
return img;
|
||||||
@@ -485,10 +483,11 @@ void ImageSlicePreview::draw(DC& dc) {
|
|||||||
mask.setAlpha(image);
|
mask.setAlpha(image);
|
||||||
if (image.HasAlpha()) {
|
if (image.HasAlpha()) {
|
||||||
// create bitmap
|
// create bitmap
|
||||||
bitmap = Bitmap(image.GetWidth(), image.GetHeight());
|
int width = image.GetWidth(), height = image.GetHeight();
|
||||||
|
bitmap = Bitmap(width, height);
|
||||||
wxMemoryDC mdc; mdc.SelectObject(bitmap);
|
wxMemoryDC mdc; mdc.SelectObject(bitmap);
|
||||||
// draw checker pattern behind image
|
// draw checker pattern behind image
|
||||||
RealRect rect = (RealRect) GetClientSize();
|
RealRect rect = RealRect(0, 0, width, height);
|
||||||
RotatedDC rdc(mdc, 0, rect, 1, QUALITY_LOW);
|
RotatedDC rdc(mdc, 0, rect, 1, QUALITY_LOW);
|
||||||
draw_checker(rdc, rect);
|
draw_checker(rdc, rect);
|
||||||
rdc.DrawImage(image, RealPoint(0,0));
|
rdc.DrawImage(image, RealPoint(0,0));
|
||||||
@@ -587,7 +586,6 @@ ImageSliceSelector::ImageSliceSelector(Window* parent, int id, ImageSlice& slice
|
|||||||
, slice(slice)
|
, slice(slice)
|
||||||
, mouse_down(false)
|
, 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) {
|
if (target_ratio > 1.0) {
|
||||||
SetMinSize(wxSize(500, 500 / target_ratio));
|
SetMinSize(wxSize(500, 500 / target_ratio));
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
wxSize target_size; ///< Size of the target image
|
wxSize target_size; ///< Size of the target image
|
||||||
wxRect selection; ///< Area to slice from source
|
wxRect selection; ///< Area to slice from source
|
||||||
Color background; ///< Color for areas outside the source image
|
Color background; ///< Color for areas outside the source image
|
||||||
bool allow_outside; ///< Allow the slice to extend outside the source image?
|
bool allow_outside; ///< Allow the slice to extend outside the source image? TODO: This currently crashes
|
||||||
bool aspect_fixed; ///< Aspect ratio lock?
|
bool aspect_fixed; ///< Aspect ratio lock?
|
||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
void centerSelectionHorizontally();
|
void centerSelectionHorizontally();
|
||||||
void centerSelectionVertically();
|
void centerSelectionVertically();
|
||||||
/// Get the sliced image
|
/// Get the sliced image
|
||||||
Image getSlice(double scale = 1.0) const;
|
Image getSlice() const;
|
||||||
|
|
||||||
// Zoom factor
|
// Zoom factor
|
||||||
inline double zoomX() const { return target_size.GetWidth() / (double)selection.width; }
|
inline double zoomX() const { return target_size.GetWidth() / (double)selection.width; }
|
||||||
@@ -68,7 +68,7 @@ public:
|
|||||||
ImageSliceWindow(Window* parent, const Image& source, const String& filename, const String& cardname, const wxSize& target_size, const AlphaMask& target_mask);
|
ImageSliceWindow(Window* parent, const Image& source, const String& filename, const String& cardname, const wxSize& target_size, const AlphaMask& target_mask);
|
||||||
|
|
||||||
/// Return the sliced image
|
/// Return the sliced image
|
||||||
Image getImage(double scale) const;
|
Image getImage() const;
|
||||||
|
|
||||||
// --------------------------------------------------- : Previously Used Settings
|
// --------------------------------------------------- : Previously Used Settings
|
||||||
|
|
||||||
|
|||||||
@@ -52,27 +52,25 @@ public:
|
|||||||
private:
|
private:
|
||||||
DECLARE_EVENT_TABLE();
|
DECLARE_EVENT_TABLE();
|
||||||
|
|
||||||
wxCheckBox* high_quality, *borders, *draw_editing, *spellcheck_enabled, *non_normal_export, *notes_export;
|
wxCheckBox* high_quality, *borders, *draw_editing, *spellcheck_enabled;
|
||||||
|
|
||||||
wxComboBox* zoom;
|
wxComboBox* zoom;
|
||||||
int zoom_int;
|
int zoom_int;
|
||||||
|
|
||||||
wxChoice* export_zoom;
|
|
||||||
|
|
||||||
void onSelectColumns(wxCommandEvent&);
|
void onSelectColumns(wxCommandEvent&);
|
||||||
void onZoomChange(wxCommandEvent&);
|
void onZoomChange(wxCommandEvent&);
|
||||||
void updateZoom();
|
void updateZoom();
|
||||||
};
|
};
|
||||||
|
|
||||||
class InternalPreferencesPage : public PreferencesPage {
|
class TransfersPreferencesPage : public PreferencesPage {
|
||||||
public:
|
public:
|
||||||
InternalPreferencesPage(Window* parent);
|
TransfersPreferencesPage(Window* parent);
|
||||||
void store() override;
|
void store() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxCheckBox* internal_image_extension;
|
wxCheckBox* non_normal_export, *bleed_export, *notes_export, *internal_image_extension;
|
||||||
|
|
||||||
wxChoice* internal_scale;
|
wxChoice* export_scale, *import_scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Preferences page for directories of programs
|
// Preferences page for directories of programs
|
||||||
@@ -116,7 +114,7 @@ PreferencesWindow::PreferencesWindow(Window* parent)
|
|||||||
wxNotebook* nb = new wxNotebook(this, ID_NOTEBOOK);
|
wxNotebook* nb = new wxNotebook(this, ID_NOTEBOOK);
|
||||||
nb->AddPage(new GlobalPreferencesPage (nb), _TITLE_("global"));
|
nb->AddPage(new GlobalPreferencesPage (nb), _TITLE_("global"));
|
||||||
nb->AddPage(new DisplayPreferencesPage(nb), _TITLE_("display"));
|
nb->AddPage(new DisplayPreferencesPage(nb), _TITLE_("display"));
|
||||||
nb->AddPage(new InternalPreferencesPage(nb), _TITLE_("internal"));
|
nb->AddPage(new TransfersPreferencesPage(nb), _TITLE_("transfers"));
|
||||||
nb->AddPage(new DirsPreferencesPage (nb), _TITLE_("directories"));
|
nb->AddPage(new DirsPreferencesPage (nb), _TITLE_("directories"));
|
||||||
nb->AddPage(new UpdatePreferencesPage (nb), _TITLE_("updates"));
|
nb->AddPage(new UpdatePreferencesPage (nb), _TITLE_("updates"));
|
||||||
|
|
||||||
@@ -216,34 +214,18 @@ DisplayPreferencesPage::DisplayPreferencesPage(Window* parent)
|
|||||||
borders = new wxCheckBox(this, wxID_ANY, _BUTTON_("show lines"));
|
borders = new wxCheckBox(this, wxID_ANY, _BUTTON_("show lines"));
|
||||||
draw_editing = new wxCheckBox(this, wxID_ANY, _BUTTON_("show editing hints"));
|
draw_editing = new wxCheckBox(this, wxID_ANY, _BUTTON_("show editing hints"));
|
||||||
spellcheck_enabled = new wxCheckBox(this, wxID_ANY, _BUTTON_("spellcheck enabled"));
|
spellcheck_enabled = new wxCheckBox(this, wxID_ANY, _BUTTON_("spellcheck enabled"));
|
||||||
non_normal_export = new wxCheckBox(this, wxID_ANY, _BUTTON_("rotation export"));
|
|
||||||
notes_export = new wxCheckBox(this, wxID_ANY, _BUTTON_("notes export"));
|
|
||||||
zoom = new wxComboBox(this, ID_ZOOM);
|
zoom = new wxComboBox(this, ID_ZOOM);
|
||||||
export_zoom = new wxChoice (this, ID_EXPORT_ZOOM);
|
|
||||||
|
|
||||||
//wxButton* columns = new wxButton(this, ID_SELECT_COLUMNS, _BUTTON_("select"));
|
|
||||||
// set values
|
// set values
|
||||||
high_quality-> SetValue( settings.default_stylesheet_settings.card_anti_alias());
|
high_quality-> SetValue( settings.default_stylesheet_settings.card_anti_alias());
|
||||||
borders-> SetValue( settings.default_stylesheet_settings.card_borders());
|
borders-> SetValue( settings.default_stylesheet_settings.card_borders());
|
||||||
draw_editing-> SetValue( settings.default_stylesheet_settings.card_draw_editing());
|
draw_editing-> SetValue( settings.default_stylesheet_settings.card_draw_editing());
|
||||||
spellcheck_enabled->SetValue( settings.default_stylesheet_settings.card_spellcheck_enabled());
|
spellcheck_enabled->SetValue( settings.default_stylesheet_settings.card_spellcheck_enabled());
|
||||||
non_normal_export-> SetValue(!settings.default_stylesheet_settings.card_normal_export());
|
zoom_int = static_cast<int>( settings.default_stylesheet_settings.card_zoom() * 100);
|
||||||
notes_export-> SetValue( settings.default_stylesheet_settings.card_notes_export());
|
zoom->SetValue(String::Format(_("%d%%"),zoom_int));
|
||||||
zoom_int = static_cast<int>(settings.default_stylesheet_settings.card_zoom() * 100);
|
for (int i : Settings::scale_choices) {
|
||||||
zoom->SetValue(String::Format(_("%d%%"),zoom_int));
|
zoom->Append(String::Format(_("%d%%"), i));
|
||||||
for (int i : Settings::export_zoom_choices) {
|
}
|
||||||
zoom->Append(String::Format(_("%d%%"), i));
|
|
||||||
}
|
|
||||||
|
|
||||||
export_zoom->Append(_LABEL_("export around 300"));
|
|
||||||
export_zoom->Append(_LABEL_("export force 300"));
|
|
||||||
export_zoom->Append(_LABEL_("export force 150"));
|
|
||||||
for (int i : Settings::export_zoom_choices) {
|
|
||||||
export_zoom->Append(String::Format(_("%d%%"), i));
|
|
||||||
}
|
|
||||||
int default_export_zoom = settings.default_stylesheet_settings.export_zoom_selection();
|
|
||||||
if (default_export_zoom < 0 || default_export_zoom > export_zoom->GetCount() - 1) default_export_zoom = 0;
|
|
||||||
export_zoom->SetSelection(default_export_zoom);
|
|
||||||
|
|
||||||
// init sizer
|
// init sizer
|
||||||
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
||||||
@@ -257,19 +239,8 @@ DisplayPreferencesPage::DisplayPreferencesPage(Window* parent)
|
|||||||
s3->AddSpacer(2);
|
s3->AddSpacer(2);
|
||||||
s3->Add(zoom);
|
s3->Add(zoom);
|
||||||
s3->Add(new wxStaticText(this, wxID_ANY, _LABEL_("percent of normal")),1, wxALL & ~wxRIGHT, 4);
|
s3->Add(new wxStaticText(this, wxID_ANY, _LABEL_("percent of normal")),1, wxALL & ~wxRIGHT, 4);
|
||||||
wxSizer* s4 = new wxBoxSizer(wxHORIZONTAL);
|
|
||||||
s4->Add(new wxStaticText(this, wxID_ANY, _LABEL_("export")), 0, wxALL & ~wxLEFT, 4);
|
|
||||||
s4->AddSpacer(2);
|
|
||||||
s4->Add(export_zoom);
|
|
||||||
//s4->Add(new wxStaticText(this, wxID_ANY, _LABEL_("percent of normal")), 1, wxALL & ~wxRIGHT, 4);
|
|
||||||
|
|
||||||
s2->Add(s3, 0, wxEXPAND | wxALL, 4);
|
s2->Add(s3, 0, wxEXPAND | wxALL, 4);
|
||||||
s2->Add(s4, 0, wxEXPAND | wxALL, 4);
|
|
||||||
s2->Add(non_normal_export, 0, wxEXPAND | wxALL, 4);
|
|
||||||
s2->Add(notes_export, 0, wxEXPAND | wxALL, 4);
|
|
||||||
|
|
||||||
s->Add(s2, 0, wxEXPAND | wxALL, 8);
|
s->Add(s2, 0, wxEXPAND | wxALL, 8);
|
||||||
|
|
||||||
s->SetSizeHints(this);
|
s->SetSizeHints(this);
|
||||||
SetSizer(s);
|
SetSizer(s);
|
||||||
}
|
}
|
||||||
@@ -279,12 +250,9 @@ void DisplayPreferencesPage::store() {
|
|||||||
settings.default_stylesheet_settings.card_borders = borders->GetValue();
|
settings.default_stylesheet_settings.card_borders = borders->GetValue();
|
||||||
settings.default_stylesheet_settings.card_draw_editing = draw_editing->GetValue();
|
settings.default_stylesheet_settings.card_draw_editing = draw_editing->GetValue();
|
||||||
settings.default_stylesheet_settings.card_spellcheck_enabled = spellcheck_enabled->GetValue();
|
settings.default_stylesheet_settings.card_spellcheck_enabled = spellcheck_enabled->GetValue();
|
||||||
settings.default_stylesheet_settings.card_normal_export = !non_normal_export->GetValue();
|
|
||||||
settings.default_stylesheet_settings.card_notes_export = notes_export->GetValue();
|
|
||||||
|
|
||||||
updateZoom();
|
updateZoom();
|
||||||
settings.default_stylesheet_settings.card_zoom = zoom_int / 100.0;
|
settings.default_stylesheet_settings.card_zoom = zoom_int / 100.0;
|
||||||
settings.default_stylesheet_settings.export_zoom_selection = export_zoom->GetSelection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayPreferencesPage::onSelectColumns(wxCommandEvent&) {
|
void DisplayPreferencesPage::onSelectColumns(wxCommandEvent&) {
|
||||||
@@ -292,7 +260,7 @@ void DisplayPreferencesPage::onSelectColumns(wxCommandEvent&) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DisplayPreferencesPage::onZoomChange(wxCommandEvent&) {
|
void DisplayPreferencesPage::onZoomChange(wxCommandEvent&) {
|
||||||
updateZoom();
|
updateZoom();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayPreferencesPage::updateZoom() {
|
void DisplayPreferencesPage::updateZoom() {
|
||||||
@@ -312,41 +280,78 @@ END_EVENT_TABLE ()
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Preferences page : internal
|
// ----------------------------------------------------------------------------- : Preferences page : internal
|
||||||
|
|
||||||
InternalPreferencesPage::InternalPreferencesPage(Window* parent) : PreferencesPage(parent) {
|
TransfersPreferencesPage::TransfersPreferencesPage(Window* parent) : PreferencesPage(parent) {
|
||||||
|
// init controls
|
||||||
|
non_normal_export = new wxCheckBox(this, wxID_ANY, _BUTTON_("rotation export"));
|
||||||
|
bleed_export = new wxCheckBox(this, wxID_ANY, _BUTTON_("bleed export"));
|
||||||
|
notes_export = new wxCheckBox(this, wxID_ANY, _BUTTON_("notes export"));
|
||||||
|
export_scale = new wxChoice (this, ID_EXPORT_ZOOM);
|
||||||
|
|
||||||
internal_image_extension = new wxCheckBox(this, wxID_ANY, _BUTTON_("internal image extension"));
|
internal_image_extension = new wxCheckBox(this, wxID_ANY, _BUTTON_("internal image extension"));
|
||||||
internal_scale = new wxChoice(this, ID_INTERNAL_SCALE);
|
import_scale = new wxChoice (this, ID_IMPORT_ZOOM);
|
||||||
|
|
||||||
|
// set values
|
||||||
|
non_normal_export-> SetValue(!settings.default_stylesheet_settings.card_normal_export());
|
||||||
|
bleed_export-> SetValue( settings.default_stylesheet_settings.card_bleed_export());
|
||||||
|
notes_export-> SetValue( settings.default_stylesheet_settings.card_notes_export());
|
||||||
|
export_scale->Append(_LABEL_("export around 300"));
|
||||||
|
export_scale->Append(_LABEL_("export force 300"));
|
||||||
|
export_scale->Append(_LABEL_("export force 150"));
|
||||||
|
for (int i : Settings::scale_choices) {
|
||||||
|
export_scale->Append(String::Format(_("%d%%"), i));
|
||||||
|
}
|
||||||
|
int default_export_scale = settings.default_stylesheet_settings.export_scale_selection();
|
||||||
|
if (default_export_scale < 0 || default_export_scale > export_scale->GetCount() - 1) default_export_scale = 0;
|
||||||
|
export_scale->SetSelection(default_export_scale);
|
||||||
|
|
||||||
internal_image_extension->SetValue(settings.internal_image_extension);
|
internal_image_extension->SetValue(settings.internal_image_extension);
|
||||||
|
import_scale->Append(_LABEL_("use export scale"));
|
||||||
internal_scale->Append(_LABEL_("use export scale"));
|
import_scale->Append(_LABEL_("export around 300"));
|
||||||
internal_scale->Append(_LABEL_("export around 300"));
|
import_scale->Append(_LABEL_("export force 300"));
|
||||||
internal_scale->Append(_LABEL_("export force 300"));
|
import_scale->Append(_LABEL_("export force 150"));
|
||||||
internal_scale->Append(_LABEL_("export force 150"));
|
for (int i : Settings::scale_choices) {
|
||||||
for (int i : Settings::export_zoom_choices) {
|
import_scale->Append(String::Format(_("%d%%"), i));
|
||||||
internal_scale->Append(String::Format(_("%d%%"), i));
|
|
||||||
}
|
}
|
||||||
int default_internal_scale = settings.internal_scale_selection;
|
int default_import_scale = settings.import_scale_selection;
|
||||||
if (default_internal_scale < 0 || default_internal_scale > internal_scale->GetCount() - 1) default_internal_scale = 0;
|
if (default_import_scale < 0 || default_import_scale > import_scale->GetCount() - 1) default_import_scale = 0;
|
||||||
internal_scale->SetSelection(default_internal_scale);
|
import_scale->SetSelection(default_import_scale);
|
||||||
|
|
||||||
|
// init sizers
|
||||||
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
||||||
wxSizer* s2 = new wxStaticBoxSizer(wxVERTICAL, this, _LABEL_("storage"));
|
wxSizer* s2 = new wxStaticBoxSizer(wxVERTICAL, this, _LABEL_("export"));
|
||||||
wxSizer* s3 = new wxBoxSizer(wxHORIZONTAL);
|
s2->Add(new wxStaticText(this, wxID_ANY, _LABEL_("export desc")), 0, wxALL & ~wxLEFT, 4);
|
||||||
s3->Add(new wxStaticText(this, wxID_ANY, _LABEL_("scale")), 0, wxALL & ~wxLEFT, 4);
|
wxSizer* s3 = new wxBoxSizer(wxHORIZONTAL);
|
||||||
s3->AddSpacer(2);
|
s3->Add(new wxStaticText(this, wxID_ANY, _LABEL_("scale")), 0, wxALL & ~wxLEFT, 4);
|
||||||
s3->Add(internal_scale);
|
s3->AddSpacer(2);
|
||||||
//s3->Add(new wxStaticText(this, wxID_ANY, _LABEL_("percent of normal")), 1, wxALL & ~wxRIGHT, 4);
|
s3->Add(export_scale);
|
||||||
s2->Add(s3);
|
s2->Add(s3, 0, wxEXPAND | wxALL, 4);
|
||||||
s2->Add(new wxStaticText(this, wxID_ANY, _LABEL_("internal scale desc")), 0, wxALL & ~wxLEFT, 4);
|
s2->Add(non_normal_export, 0, wxEXPAND | wxALL, 4);
|
||||||
s2->Add(internal_image_extension, 0, wxEXPAND | wxALL, 4);
|
s2->Add(bleed_export, 0, wxEXPAND | wxALL, 4);
|
||||||
s->Add(s2, 0, wxEXPAND | wxALL, 8);
|
s2->Add(notes_export, 0, wxEXPAND | wxALL, 4);
|
||||||
|
wxSizer* s5 = new wxStaticBoxSizer(wxVERTICAL, this, _LABEL_("import"));
|
||||||
|
s5->Add(new wxStaticText(this, wxID_ANY, _LABEL_("import desc")), 0, wxALL & ~wxLEFT, 4);
|
||||||
|
wxSizer* s6 = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
s6->Add(new wxStaticText(this, wxID_ANY, _LABEL_("scale")), 0, wxALL & ~wxLEFT, 4);
|
||||||
|
s6->AddSpacer(2);
|
||||||
|
s6->Add(import_scale);
|
||||||
|
s5->Add(s6, 0, wxEXPAND | wxALL & ~wxBottom, 4);
|
||||||
|
s5->Add(new wxStaticText(this, wxID_ANY, _LABEL_("internal scale desc")), 0, wxALL & ~wxTOP, 4);
|
||||||
|
s5->Add(internal_image_extension, 0, wxEXPAND | wxALL, 4);
|
||||||
|
s->Add(s2, 0, wxEXPAND | wxALL, 8);
|
||||||
|
s->Add(s5, 0, wxEXPAND | wxALL, 8);
|
||||||
|
export_scale->SetFocus();
|
||||||
s->SetSizeHints(this);
|
s->SetSizeHints(this);
|
||||||
SetSizer(s);
|
SetSizer(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InternalPreferencesPage::store() {
|
void TransfersPreferencesPage::store() {
|
||||||
settings.internal_image_extension = internal_image_extension->GetValue();
|
settings.default_stylesheet_settings.card_normal_export = !non_normal_export->GetValue();
|
||||||
settings.internal_scale_selection = internal_scale->GetSelection();
|
settings.default_stylesheet_settings.card_bleed_export = bleed_export->GetValue();
|
||||||
|
settings.default_stylesheet_settings.card_notes_export = notes_export->GetValue();
|
||||||
|
settings.default_stylesheet_settings.export_scale_selection = export_scale->GetSelection();
|
||||||
|
|
||||||
|
settings.internal_image_extension = internal_image_extension->GetValue();
|
||||||
|
settings.import_scale_selection = import_scale->GetSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Preferences page : directories
|
// ----------------------------------------------------------------------------- : Preferences page : directories
|
||||||
|
|||||||
+11
-18
@@ -50,31 +50,24 @@ bool ImageValueEditor::onLeftDClick(const RealPoint&, wxMouseEvent&) {
|
|||||||
|
|
||||||
void ImageValueEditor::sliceImage(const Image& image, const String& filename, const String& cardname) {
|
void ImageValueEditor::sliceImage(const Image& image, const String& filename, const String& cardname) {
|
||||||
if (!image.Ok()) return;
|
if (!image.Ok()) return;
|
||||||
|
// determine import scale based on the user's settings.
|
||||||
|
double import_scale = 1.0;
|
||||||
|
StyleSheetP stylesheet = editor().getCard()->stylesheet;
|
||||||
|
if (!stylesheet) stylesheet = editor().getSet()->stylesheet;
|
||||||
|
if (stylesheet) import_scale = settings.importScaleSettingsFor(*stylesheet);
|
||||||
|
RealSize target_size = RealSize(style().getSize() * import_scale);
|
||||||
|
target_size = RealSize((int)target_size.width, (int)target_size.height);
|
||||||
// mask
|
// mask
|
||||||
GeneratedImage::Options options((int)style().width, (int)style().height, &parent.getStylePackage(), &parent.getLocalPackage());
|
GeneratedImage::Options options((int)target_size.width, (int)target_size.height, &parent.getStylePackage(), &parent.getLocalPackage());
|
||||||
AlphaMask mask;
|
AlphaMask mask;
|
||||||
style().mask.getNoCache(options,mask);
|
style().mask.getNoCache(options, mask);
|
||||||
// slice
|
// slice
|
||||||
ImageSliceWindow s(wxGetTopLevelParent(&editor()), image, filename, cardname, style().getSize(), mask);
|
ImageSliceWindow s(wxGetTopLevelParent(&editor()), image, filename, cardname, target_size, mask);
|
||||||
// clicked ok?
|
// clicked ok?
|
||||||
if (s.ShowModal() == wxID_OK) {
|
if (s.ShowModal() == wxID_OK) {
|
||||||
// store the image into the set
|
// store the image into the set
|
||||||
LocalFileName new_image_file = getLocalPackage().newFileName(field().name, settings.internal_image_extension ? _(".png") : _("")); // a new unique name in the package
|
LocalFileName new_image_file = getLocalPackage().newFileName(field().name, settings.internal_image_extension ? _(".png") : _("")); // a new unique name in the package
|
||||||
|
Image img = s.getImage();
|
||||||
// Specify a desired size based on the stylesheet and a scale multiplier defined within the user's settings.
|
|
||||||
// Storing at a greater than 100% resolution allows for better exports >100%, but may change how images look when filters (sharpen) are applied.
|
|
||||||
// It also disrupts some of the patterns in use for doing popout planeswalkers since you have to do the math at both scales.
|
|
||||||
// Additionally, this bloats the set file size as even under-resolution images are upscaled to the new minimum size.
|
|
||||||
double internal_scale = 1.0;
|
|
||||||
try {
|
|
||||||
// surrounding this in try catch to be safe for now. maybe this is overkill
|
|
||||||
StyleSheetP stylesheet = editor().getCard()->stylesheet;
|
|
||||||
if (!stylesheet) stylesheet = editor().getSet()->stylesheet;
|
|
||||||
internal_scale = settings.internalScaleSettingsFor(*stylesheet);
|
|
||||||
} catch (...) {
|
|
||||||
queue_message(MESSAGE_ERROR, _("Could not find stylesheet to determine export zoom.\nfilename: " + filename + _("\ncardname: " + cardname)));
|
|
||||||
}
|
|
||||||
Image img = s.getImage(internal_scale);
|
|
||||||
img.SaveFile(getLocalPackage().nameOut(new_image_file), wxBITMAP_TYPE_PNG); // always use PNG images, see #69. Disk space is cheap anyway.
|
img.SaveFile(getLocalPackage().nameOut(new_image_file), wxBITMAP_TYPE_PNG); // always use PNG images, see #69. Disk space is cheap anyway.
|
||||||
addAction(value_action(valueP(), new_image_file));
|
addAction(value_action(valueP(), new_image_file));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -759,6 +759,22 @@ SCRIPT_FUNCTION(get_card_stylesheet) {
|
|||||||
throw ScriptError(_("invalid set or card argument"));
|
throw ScriptError(_("invalid set or card argument"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCRIPT_FUNCTION(get_card_export_settings) {
|
||||||
|
SCRIPT_PARAM_C(ScriptValueP, input);
|
||||||
|
SCRIPT_PARAM_C(ScriptValueP, set);
|
||||||
|
ScriptObject<CardP>* c = dynamic_cast<ScriptObject<CardP>*>(input.get());
|
||||||
|
ScriptObject<Set*>* s = dynamic_cast<ScriptObject<Set*>*>(set.get());
|
||||||
|
if (s && c) {
|
||||||
|
Settings::ExportSettings card_settings = settings.exportSettingsFor(s->getValue()->stylesheetFor(c->getValue()));
|
||||||
|
ScriptCustomCollectionP ret(new ScriptCustomCollection());
|
||||||
|
ret->value.push_back(to_script(lround(card_settings.zoom * 100)));
|
||||||
|
ret->value.push_back(to_script(lround(rad_to_deg(card_settings.angle_radians))));
|
||||||
|
ret->value.push_back(to_script(lround(card_settings.bleed_pixels)));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
throw ScriptError(_("invalid set or card argument"));
|
||||||
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(get_card_from_uid) {
|
SCRIPT_FUNCTION(get_card_from_uid) {
|
||||||
SCRIPT_PARAM_C(Set*, set);
|
SCRIPT_PARAM_C(Set*, set);
|
||||||
SCRIPT_PARAM_C(String, input);
|
SCRIPT_PARAM_C(String, input);
|
||||||
@@ -999,82 +1015,83 @@ SCRIPT_FUNCTION(rule) {
|
|||||||
|
|
||||||
void init_script_basic_functions(Context& ctx) {
|
void init_script_basic_functions(Context& ctx) {
|
||||||
// app info
|
// app info
|
||||||
ctx.setVariable(_("get_mse_version"), script_get_mse_version);
|
ctx.setVariable(_("get_mse_version"), script_get_mse_version);
|
||||||
ctx.setVariable(_("get_mse_locale"), script_get_mse_locale);
|
ctx.setVariable(_("get_mse_locale"), script_get_mse_locale);
|
||||||
ctx.setVariable(_("get_mse_path"), script_get_mse_path);
|
ctx.setVariable(_("get_mse_path"), script_get_mse_path);
|
||||||
ctx.setVariable(_("get_mse_dark_mode"), script_get_mse_dark_mode);
|
ctx.setVariable(_("get_mse_dark_mode"), script_get_mse_dark_mode);
|
||||||
// debugging
|
// debugging
|
||||||
ctx.setVariable(_("trace"), script_trace);
|
ctx.setVariable(_("trace"), script_trace);
|
||||||
ctx.setVariable(_("warning"), script_warning);
|
ctx.setVariable(_("warning"), script_warning);
|
||||||
ctx.setVariable(_("error"), script_error);
|
ctx.setVariable(_("error"), script_error);
|
||||||
ctx.setVariable(_("exists_in_package"), script_exists_in_package);
|
ctx.setVariable(_("exists_in_package"), script_exists_in_package);
|
||||||
// conversion
|
// conversion
|
||||||
ctx.setVariable(_("to_string"), script_to_string);
|
ctx.setVariable(_("to_string"), script_to_string);
|
||||||
ctx.setVariable(_("to_int"), script_to_int);
|
ctx.setVariable(_("to_int"), script_to_int);
|
||||||
ctx.setVariable(_("to_real"), script_to_real);
|
ctx.setVariable(_("to_real"), script_to_real);
|
||||||
ctx.setVariable(_("to_number"), script_to_number);
|
ctx.setVariable(_("to_number"), script_to_number);
|
||||||
ctx.setVariable(_("to_boolean"), script_to_boolean);
|
ctx.setVariable(_("to_boolean"), script_to_boolean);
|
||||||
ctx.setVariable(_("to_color"), script_to_color);
|
ctx.setVariable(_("to_color"), script_to_color);
|
||||||
ctx.setVariable(_("to_date"), script_to_date);
|
ctx.setVariable(_("to_date"), script_to_date);
|
||||||
ctx.setVariable(_("to_code"), script_to_code);
|
ctx.setVariable(_("to_code"), script_to_code);
|
||||||
ctx.setVariable(_("to_json"), script_to_json);
|
ctx.setVariable(_("to_json"), script_to_json);
|
||||||
ctx.setVariable(_("from_json"), script_from_json);
|
ctx.setVariable(_("from_json"), script_from_json);
|
||||||
ctx.setVariable(_("type_name"), script_type_name);
|
ctx.setVariable(_("type_name"), script_type_name);
|
||||||
ctx.setVariable(_("make_map"), script_make_map);
|
ctx.setVariable(_("make_map"), script_make_map);
|
||||||
ctx.setVariable(_("get_card_styling"), script_get_card_styling);
|
ctx.setVariable(_("get_card_styling"), script_get_card_styling);
|
||||||
ctx.setVariable(_("get_card_stylesheet"), script_get_card_stylesheet);
|
ctx.setVariable(_("get_card_stylesheet"), script_get_card_stylesheet);
|
||||||
|
ctx.setVariable(_("get_card_export_settings"), script_get_card_export_settings);
|
||||||
|
ctx.setVariable(_("get_card_from_uid"), script_get_card_from_uid);
|
||||||
|
ctx.setVariable(_("get_cards_from_link"), script_get_cards_from_link);
|
||||||
|
ctx.setVariable(_("get_back_face"), script_get_back_face);
|
||||||
|
ctx.setVariable(_("get_front_face"), script_get_front_face);
|
||||||
|
ctx.setVariable(_("has_link"), script_has_link);
|
||||||
// math
|
// math
|
||||||
ctx.setVariable(_("abs"), script_abs);
|
ctx.setVariable(_("abs"), script_abs);
|
||||||
ctx.setVariable(_("random_real"), script_random_real);
|
ctx.setVariable(_("random_real"), script_random_real);
|
||||||
ctx.setVariable(_("random_int"), script_random_int);
|
ctx.setVariable(_("random_int"), script_random_int);
|
||||||
ctx.setVariable(_("random_boolean"), script_random_boolean);
|
ctx.setVariable(_("random_boolean"), script_random_boolean);
|
||||||
ctx.setVariable(_("sin"), script_sin);
|
ctx.setVariable(_("sin"), script_sin);
|
||||||
ctx.setVariable(_("cos"), script_cos);
|
ctx.setVariable(_("cos"), script_cos);
|
||||||
ctx.setVariable(_("tan"), script_tan);
|
ctx.setVariable(_("tan"), script_tan);
|
||||||
ctx.setVariable(_("sin_deg"), script_sin_deg);
|
ctx.setVariable(_("sin_deg"), script_sin_deg);
|
||||||
ctx.setVariable(_("cos_deg"), script_cos_deg);
|
ctx.setVariable(_("cos_deg"), script_cos_deg);
|
||||||
ctx.setVariable(_("tan_deg"), script_tan_deg);
|
ctx.setVariable(_("tan_deg"), script_tan_deg);
|
||||||
ctx.setVariable(_("exp"), script_exp);
|
ctx.setVariable(_("exp"), script_exp);
|
||||||
ctx.setVariable(_("log"), script_log);
|
ctx.setVariable(_("log"), script_log);
|
||||||
ctx.setVariable(_("log10"), script_log10);
|
ctx.setVariable(_("log10"), script_log10);
|
||||||
ctx.setVariable(_("sqrt"), script_sqrt);
|
ctx.setVariable(_("sqrt"), script_sqrt);
|
||||||
ctx.setVariable(_("pow"), script_pow);
|
ctx.setVariable(_("pow"), script_pow);
|
||||||
// string
|
// string
|
||||||
ctx.setVariable(_("to_upper"), script_to_upper);
|
ctx.setVariable(_("to_upper"), script_to_upper);
|
||||||
ctx.setVariable(_("to_lower"), script_to_lower);
|
ctx.setVariable(_("to_lower"), script_to_lower);
|
||||||
ctx.setVariable(_("to_title"), script_to_title);
|
ctx.setVariable(_("to_title"), script_to_title);
|
||||||
ctx.setVariable(_("reverse"), script_reverse);
|
ctx.setVariable(_("reverse"), script_reverse);
|
||||||
ctx.setVariable(_("trim"), script_trim);
|
ctx.setVariable(_("trim"), script_trim);
|
||||||
ctx.setVariable(_("substring"), script_substring);
|
ctx.setVariable(_("substring"), script_substring);
|
||||||
ctx.setVariable(_("contains"), script_contains);
|
ctx.setVariable(_("contains"), script_contains);
|
||||||
ctx.setVariable(_("format"), script_format);
|
ctx.setVariable(_("format"), script_format);
|
||||||
ctx.setVariable(_("format_rule"), make_intrusive<ScriptRule>(script_format));
|
ctx.setVariable(_("format_rule"), make_intrusive<ScriptRule>(script_format));
|
||||||
ctx.setVariable(_("curly_quotes"), script_curly_quotes);
|
ctx.setVariable(_("curly_quotes"), script_curly_quotes);
|
||||||
ctx.setVariable(_("regex_escape"), script_regex_escape);
|
ctx.setVariable(_("regex_escape"), script_regex_escape);
|
||||||
ctx.setVariable(_("sort_text"), script_sort_text);
|
ctx.setVariable(_("sort_text"), script_sort_text);
|
||||||
ctx.setVariable(_("sort_rule"), make_intrusive<ScriptRule>(script_sort_text));
|
ctx.setVariable(_("sort_rule"), make_intrusive<ScriptRule>(script_sort_text));
|
||||||
// tagged string
|
// tagged string
|
||||||
ctx.setVariable(_("tag_contents"), script_tag_contents);
|
ctx.setVariable(_("tag_contents"), script_tag_contents);
|
||||||
ctx.setVariable(_("remove_tag"), script_remove_tag);
|
ctx.setVariable(_("remove_tag"), script_remove_tag);
|
||||||
ctx.setVariable(_("remove_tags"), script_remove_tags);
|
ctx.setVariable(_("remove_tags"), script_remove_tags);
|
||||||
ctx.setVariable(_("tag_contents_rule"), make_intrusive<ScriptRule>(script_tag_contents));
|
ctx.setVariable(_("tag_contents_rule"), make_intrusive<ScriptRule>(script_tag_contents));
|
||||||
ctx.setVariable(_("tag_remove_rule"), make_intrusive<ScriptRule>(script_remove_tag));
|
ctx.setVariable(_("tag_remove_rule"), make_intrusive<ScriptRule>(script_remove_tag));
|
||||||
// collection
|
// collection
|
||||||
ctx.setVariable(_("position"), script_position_of);
|
ctx.setVariable(_("position"), script_position_of);
|
||||||
ctx.setVariable(_("length"), script_length);
|
ctx.setVariable(_("length"), script_length);
|
||||||
ctx.setVariable(_("number_of_items"), script_number_of_items); // deprecated
|
ctx.setVariable(_("number_of_items"), script_number_of_items); // deprecated
|
||||||
ctx.setVariable(_("filter_list"), script_filter_list);
|
ctx.setVariable(_("filter_list"), script_filter_list);
|
||||||
ctx.setVariable(_("sort_list"), script_sort_list);
|
ctx.setVariable(_("sort_list"), script_sort_list);
|
||||||
ctx.setVariable(_("random_shuffle"), script_random_shuffle);
|
ctx.setVariable(_("random_shuffle"), script_random_shuffle);
|
||||||
ctx.setVariable(_("random_select"), script_random_select);
|
ctx.setVariable(_("random_select"), script_random_select);
|
||||||
ctx.setVariable(_("random_select_many"), script_random_select_many);
|
ctx.setVariable(_("random_select_many"), script_random_select_many);
|
||||||
ctx.setVariable(_("get_card_from_uid"), script_get_card_from_uid);
|
|
||||||
ctx.setVariable(_("get_cards_from_link"), script_get_cards_from_link);
|
|
||||||
ctx.setVariable(_("get_back_face"), script_get_back_face);
|
|
||||||
ctx.setVariable(_("get_front_face"), script_get_front_face);
|
|
||||||
ctx.setVariable(_("has_link"), script_has_link);
|
|
||||||
// keyword
|
// keyword
|
||||||
ctx.setVariable(_("expand_keywords"), script_expand_keywords);
|
ctx.setVariable(_("expand_keywords"), script_expand_keywords);
|
||||||
ctx.setVariable(_("expand_keywords_rule"), make_intrusive<ScriptRule>(script_expand_keywords));
|
ctx.setVariable(_("expand_keywords_rule"), make_intrusive<ScriptRule>(script_expand_keywords));
|
||||||
ctx.setVariable(_("keyword_usage"), script_keyword_usage);
|
ctx.setVariable(_("keyword_usage"), script_keyword_usage);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -428,22 +428,38 @@ SCRIPT_FUNCTION(write_image_file) {
|
|||||||
SCRIPT_RETURN(file); // already written an image with this name
|
SCRIPT_RETURN(file); // already written an image with this name
|
||||||
}
|
}
|
||||||
// get image
|
// get image
|
||||||
|
Image img;
|
||||||
|
SCRIPT_PARAM(Set*, set);
|
||||||
SCRIPT_PARAM_C(ScriptValueP, input);
|
SCRIPT_PARAM_C(ScriptValueP, input);
|
||||||
SCRIPT_OPTIONAL_PARAM_(int, width);
|
ScriptObject<CardP>* card = dynamic_cast<ScriptObject<CardP>*>(input.get()); // is the input a card or image?
|
||||||
SCRIPT_OPTIONAL_PARAM_(int, height);
|
|
||||||
ScriptObject<CardP>* card = dynamic_cast<ScriptObject<CardP>*>(input.get()); // is it a card?
|
|
||||||
Image image;
|
|
||||||
GeneratedImage::Options options(width, height, ei.export_template.get(), ei.set.get());
|
|
||||||
if (card) {
|
if (card) {
|
||||||
image = conform_image(export_image(ei.set, card->getValue()), options);
|
SCRIPT_PARAM_DEFAULT(double, zoom, 100.0);
|
||||||
|
SCRIPT_PARAM_DEFAULT(Degrees, angle, 0.0);
|
||||||
|
SCRIPT_PARAM_DEFAULT(double, bleed, 0.0);
|
||||||
|
SCRIPT_PARAM_DEFAULT(bool, use_user_settings, false);
|
||||||
|
if (use_user_settings) {
|
||||||
|
// Use the User's Preferences for Export Zoom, Angle and Bleed settings.
|
||||||
|
Settings::ExportSettings card_settings = settings.exportSettingsFor(set->stylesheetFor(card->getValue()));
|
||||||
|
zoom = card_settings.zoom;
|
||||||
|
angle = card_settings.angle_radians;
|
||||||
|
bleed = card_settings.bleed_pixels;
|
||||||
|
} else {
|
||||||
|
// Use the provided (or defaulted) Zoom, Angle and Bleed.
|
||||||
|
zoom = zoom / 100.0;
|
||||||
|
angle = deg_to_rad(angle);
|
||||||
|
}
|
||||||
|
img = export_image(set, card->getValue(), true, zoom, angle, bleed);
|
||||||
} else {
|
} else {
|
||||||
image = input->toImage()->generateConform(options);
|
SCRIPT_OPTIONAL_PARAM_(int, width)
|
||||||
|
SCRIPT_OPTIONAL_PARAM_(int, height)
|
||||||
|
GeneratedImage::Options options(width, height, ei.export_template.get(), ei.set.get());
|
||||||
|
img = input->toImage()->generateConform(options);
|
||||||
}
|
}
|
||||||
if (!image.Ok()) throw Error(_("Unable to generate image for file ") + file);
|
if (!img.Ok()) throw Error(_("Unable to generate image for file ") + file);
|
||||||
// write
|
// write
|
||||||
ensure_dir_valid(out_path);
|
ensure_dir_valid(out_path);
|
||||||
image.SaveFile(out_path);
|
img.SaveFile(out_path);
|
||||||
ei.exported_images.insert(make_pair(file, wxSize(image.GetWidth(), image.GetHeight())));
|
ei.exported_images.insert(make_pair(file, wxSize(img.GetWidth(), img.GetHeight())));
|
||||||
SCRIPT_RETURN(file);
|
SCRIPT_RETURN(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,19 +35,20 @@ SCRIPT_FUNCTION(to_card_image) {
|
|||||||
SCRIPT_PARAM(CardP, input);
|
SCRIPT_PARAM(CardP, input);
|
||||||
SCRIPT_PARAM_DEFAULT(double, zoom, 100.0);
|
SCRIPT_PARAM_DEFAULT(double, zoom, 100.0);
|
||||||
SCRIPT_PARAM_DEFAULT(Degrees, angle, 0.0);
|
SCRIPT_PARAM_DEFAULT(Degrees, angle, 0.0);
|
||||||
|
SCRIPT_PARAM_DEFAULT(double, bleed, 0.0);
|
||||||
SCRIPT_PARAM_DEFAULT(bool, use_user_settings, false);
|
SCRIPT_PARAM_DEFAULT(bool, use_user_settings, false);
|
||||||
if (use_user_settings) {
|
if (use_user_settings) {
|
||||||
// Use the User's Preferences for Export Zoom and Angle settings.
|
// Use the User's Preferences for Export Zoom, Angle and Bleed settings.
|
||||||
const StyleSheet& stylesheet = set->stylesheetFor(input);
|
Settings::ExportSettings card_settings = settings.exportSettingsFor(set->stylesheetFor(input));
|
||||||
StyleSheetSettings& stylesheet_settings = settings.stylesheetSettingsFor(stylesheet);
|
zoom = card_settings.zoom;
|
||||||
zoom = settings.exportZoomSettingsFor(stylesheet);
|
angle = card_settings.angle_radians;
|
||||||
angle = stylesheet_settings.card_normal_export() ? 0.0 : deg_to_rad(stylesheet_settings.card_angle());
|
bleed = card_settings.bleed_pixels;
|
||||||
} else {
|
} else {
|
||||||
// Use the provided (or defaulted) Zoom and Angle.
|
// Use the provided (or defaulted) Zoom, Angle and Bleed.
|
||||||
zoom = zoom / 100.0;
|
zoom = zoom / 100.0;
|
||||||
angle = deg_to_rad(angle);
|
angle = deg_to_rad(angle);
|
||||||
}
|
}
|
||||||
return make_intrusive<ArbitraryImage>(export_image(set, input, zoom, angle));
|
return make_intrusive<ArbitraryImage>(export_image(set, input, true, zoom, angle, bleed));
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(import_image) {
|
SCRIPT_FUNCTION(import_image) {
|
||||||
|
|||||||
@@ -363,7 +363,8 @@ inline static ScriptValueP json_to_mse(const String& string, Set* set) {
|
|||||||
boost::json::parse_options options;
|
boost::json::parse_options options;
|
||||||
options.allow_invalid_utf8 = true;
|
options.allow_invalid_utf8 = true;
|
||||||
boost::json::value jv = boost::json::parse(string.ToStdString(), ec, {}, options);
|
boost::json::value jv = boost::json::parse(string.ToStdString(), ec, {}, options);
|
||||||
if(ec) return script_nil; //queue_message(MESSAGE_ERROR, _ERROR_("json cant parse") + _("\n\n") + ec.message());
|
//if(ec) queue_message(MESSAGE_ERROR, _ERROR_("json cant parse") + _("\n\n") + ec.message());
|
||||||
|
if(ec) return script_nil;
|
||||||
return json_to_mse(jv, set);
|
return json_to_mse(jv, set);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ const Radians rad360 = 2.0*M_PI;
|
|||||||
|
|
||||||
/// Are two floating point numbers equal up to a small epsilon?
|
/// Are two floating point numbers equal up to a small epsilon?
|
||||||
inline bool almost_equal(double x, double y) {
|
inline bool almost_equal(double x, double y) {
|
||||||
return fabs(x-y) < 1e-10;
|
return fabs(x-y) < 1e-5;
|
||||||
}
|
}
|
||||||
inline bool is_rad0(double x) {
|
inline bool is_rad0(double x) {
|
||||||
return almost_equal(x,0) || almost_equal(x,rad360);
|
return almost_equal(x,0) || almost_equal(x,rad360);
|
||||||
|
|||||||
+23
-17
@@ -54,42 +54,48 @@ public:
|
|||||||
inline String const& toStringForKey() const { return fn; }
|
inline String const& toStringForKey() const { return fn; }
|
||||||
|
|
||||||
/// Retreive a rect from a filename
|
/// Retreive a rect from a filename
|
||||||
inline static wxRect getExternalRect(const String& filename) {
|
inline static void getExternalRect(const String& filename, wxRect& rect_out, int& degrees_out) {
|
||||||
size_t first = filename.find(_("---"));
|
size_t first = filename.find(_("---"));
|
||||||
if (first == String::npos) return wxRect();
|
if (first == String::npos) return;
|
||||||
size_t last = filename.find(_("---"), first+3);
|
size_t last = filename.find(_("---"), first+3);
|
||||||
if (last == String::npos) return wxRect();
|
if (last == String::npos) return;
|
||||||
String string = filename.substr(first + 3, last - (first + 3));
|
String string = filename.substr(first + 3, last - (first + 3));
|
||||||
if (string.empty()) return wxRect();
|
if (string.empty()) return;
|
||||||
|
|
||||||
size_t divider = string.find(_("-"));
|
size_t divider = string.find(_("-"));
|
||||||
if (divider == String::npos) return wxRect();
|
if (divider == String::npos) return;
|
||||||
if (divider == 0) return wxRect();
|
if (divider == 0) return;
|
||||||
int x;
|
int x;
|
||||||
if(!string.substr(0, divider).ToInt(&x)) return wxRect();
|
if(!string.substr(0, divider).ToInt(&x)) return;
|
||||||
string = string.substr(divider + 1);
|
string = string.substr(divider + 1);
|
||||||
|
|
||||||
divider = string.find(_("-"));
|
divider = string.find(_("-"));
|
||||||
if (divider == String::npos) return wxRect();
|
if (divider == String::npos) return;
|
||||||
if (divider == 0) return wxRect();
|
if (divider == 0) return;
|
||||||
int y;
|
int y;
|
||||||
if(!string.substr(0, divider).ToInt(&y)) return wxRect();
|
if(!string.substr(0, divider).ToInt(&y)) return;
|
||||||
string = string.substr(divider + 1);
|
string = string.substr(divider + 1);
|
||||||
|
|
||||||
divider = string.find(_("-"));
|
divider = string.find(_("-"));
|
||||||
if (divider == String::npos) return wxRect();
|
if (divider == String::npos) return;
|
||||||
if (divider == 0) return wxRect();
|
if (divider == 0) return;
|
||||||
int width;
|
int width;
|
||||||
if(!string.substr(0, divider).ToInt(&width)) return wxRect();
|
if(!string.substr(0, divider).ToInt(&width)) return;
|
||||||
string = string.substr(divider + 1);
|
string = string.substr(divider + 1);
|
||||||
|
|
||||||
|
divider = string.find(_("-"));
|
||||||
|
if (divider == String::npos) return;
|
||||||
|
if (divider == 0) return;
|
||||||
int height;
|
int height;
|
||||||
if(!string.ToInt(&height)) return wxRect();
|
if(!string.substr(0, divider).ToInt(&height)) return;
|
||||||
|
string = string.substr(divider + 1);
|
||||||
|
|
||||||
return wxRect(x, y, width, height);
|
if(!string.ToInt(°rees_out)) return;
|
||||||
|
|
||||||
|
rect_out = wxRect(x, y, width, height);
|
||||||
}
|
}
|
||||||
inline wxRect getExternalRect() {
|
inline void getExternalRect(wxRect& rect_out, int& degrees_out) {
|
||||||
return getExternalRect(fn);
|
getExternalRect(fn, rect_out, degrees_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ RealSize Rotation::trSizeToBB(const RealSize& size) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RealRect Rotation::trRectToBB(const RealRect& r) const {
|
RealRect Rotation::trRectToBB(const RealRect& r) const {
|
||||||
const bool special_case_optimization = false;
|
const bool special_case_optimization = true;
|
||||||
double x = r.x * zoomX, y = r.y * zoomY;
|
double x = r.x * zoomX, y = r.y * zoomY;
|
||||||
double w = r.width * zoomX, h = r.height * zoomY;
|
double w = r.width * zoomX, h = r.height * zoomY;
|
||||||
if (special_case_optimization && is_rad0(angle)) {
|
if (special_case_optimization && is_rad0(angle)) {
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ enum ControlID {
|
|||||||
ID_SHARPEN,
|
ID_SHARPEN,
|
||||||
ID_SHARPEN_AMOUNT,
|
ID_SHARPEN_AMOUNT,
|
||||||
// Internal window
|
// Internal window
|
||||||
ID_INTERNAL_SCALE,
|
ID_IMPORT_ZOOM,
|
||||||
// Updates window
|
// Updates window
|
||||||
ID_PACKAGE_LIST,
|
ID_PACKAGE_LIST,
|
||||||
ID_KEEP,
|
ID_KEEP,
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ $built_in_functions = array(
|
|||||||
'get_card_from_uid' =>'',
|
'get_card_from_uid' =>'',
|
||||||
'get_card_styling' =>'',
|
'get_card_styling' =>'',
|
||||||
'get_card_stylesheet' =>'',
|
'get_card_stylesheet' =>'',
|
||||||
|
'get_card_export_settings' =>'',
|
||||||
'add_card_to_set' =>'',
|
'add_card_to_set' =>'',
|
||||||
// html export
|
// html export
|
||||||
'to_html' =>'',
|
'to_html' =>'',
|
||||||
|
|||||||
Reference in New Issue
Block a user