From fa25da3d395e183371672f49ad6039868f7c6e62 Mon Sep 17 00:00:00 2001 From: TomTkacz Date: Mon, 10 Mar 2025 04:33:42 -0500 Subject: [PATCH 01/10] implemented import_image function --- src/gfx/generated_image.cpp | 48 +++++++++++++++++++++++++++ src/gfx/generated_image.hpp | 14 +++++++- src/script/functions/construction.cpp | 5 +++ src/script/functions/image.cpp | 6 ++++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/gfx/generated_image.cpp b/src/gfx/generated_image.cpp index 8d0ef742..5dc915b9 100644 --- a/src/gfx/generated_image.cpp +++ b/src/gfx/generated_image.cpp @@ -14,6 +14,7 @@ #include #include #include // load_resource_image +#include // ----------------------------------------------------------------------------- : GeneratedImage @@ -515,3 +516,50 @@ bool ImageValueToImage::operator == (const GeneratedImage& that) const { return that2 && filename == that2->filename && age == that2->age; } + +// ----------------------------------------------------------------------------- : ExternalImage + +Image ExternalImage::generate(const Options& opt) const { + wxFileName fname(filepath, wxPATH_UNIX); + + // does the file pointed to by filepath exist? + if (!fname.FileExists()) { + String filePathString = fname.GetAbsolutePath().ToStdString(); + throw ScriptError(format_string(_("The file '%s' was not found."),filePathString)); + } + + String fileExt = fname.GetExt(); + wxBitmapType bitmapType; + if (fileExt == _("png")) + bitmapType = wxBITMAP_TYPE_PNG; + else if (fileExt == _("jpg")) + bitmapType = wxBITMAP_TYPE_JPEG; + else + bitmapType = wxBITMAP_TYPE_BMP; + + // does the file exist in the package? + String fileNameNoExtension = fname.GetName(); + if (!opt.local_package->existsIn(fileNameNoExtension)) { + auto outStream = opt.local_package->openOut(fileNameNoExtension); + wxFileInputStream inStream = wxFileInputStream(filepath.ToStdString()); + if (!inStream.IsOk()) throw ScriptError("Failed to create file stream."); + outStream->Write(inStream); + if (!outStream->IsOk()) throw ScriptError("Failed to write image to set."); + outStream->Close(); + } + + // save the package with the new image + opt.local_package->saveAs(opt.local_package->relativeFilename(), false, false); + + auto imageInputStream = opt.local_package->openIn(fileNameNoExtension); + Image img(*imageInputStream.get(), bitmapType); + + if (!img.IsOk()) throw ScriptError("The image could not be created."); + + return img; +} + +bool ExternalImage::operator == (const GeneratedImage& that) const { + const ExternalImage* that2 = dynamic_cast(&that); + return that2 && that2->filepath == filepath; +} diff --git a/src/gfx/generated_image.hpp b/src/gfx/generated_image.hpp index d1e78221..42941923 100644 --- a/src/gfx/generated_image.hpp +++ b/src/gfx/generated_image.hpp @@ -398,4 +398,16 @@ private: LocalFileName filename; Age age; ///< Age the image was last updated }; - + +// ----------------------------------------------------------------------------- : ExternalImage + +/// Load an image from the filesystem +class ExternalImage : public GeneratedImage { +public: + ExternalImage(const String& filepath) : filepath(filepath) {}; + Image generate(const Options&) const override; + bool operator == (const GeneratedImage& that) const override; + inline String toString() { return filepath; } +private: + String filepath; +}; diff --git a/src/script/functions/construction.cpp b/src/script/functions/construction.cpp index d876d579..468bdd80 100644 --- a/src/script/functions/construction.cpp +++ b/src/script/functions/construction.cpp @@ -14,9 +14,11 @@ #include #include #include +#include #include #include #include +#include // ----------------------------------------------------------------------------- : new_card @@ -45,6 +47,9 @@ SCRIPT_FUNCTION(new_card) { pvalue->package_name = v->toString(); } else if (ColorValue* cvalue = dynamic_cast(value)) { cvalue->value = v->toColor(); + } else if (ImageValue* ivalue = dynamic_cast(value)) { + wxFileName fname( static_cast(v.get())->toString() ); + ivalue->filename = LocalFileName::fromReadString( fname.GetName(), ""); } else { throw ScriptError(format_string(_("Can not set value '%s', it is not of the right type"),name)); } diff --git a/src/script/functions/image.cpp b/src/script/functions/image.cpp index 23951556..927d529b 100644 --- a/src/script/functions/image.cpp +++ b/src/script/functions/image.cpp @@ -43,6 +43,11 @@ SCRIPT_FUNCTION(to_card_image) { return make_intrusive(export_bitmap(set, input, (zoom / 100), deg_to_rad(angle)).ConvertToImage()); } } + +SCRIPT_FUNCTION(import_image) { + SCRIPT_PARAM(String, path); + return make_intrusive(path); +} // ----------------------------------------------------------------------------- : Image functions @@ -261,4 +266,5 @@ void init_script_image_functions(Context& ctx) { ctx.setVariable(_("drop_shadow"), script_drop_shadow); ctx.setVariable(_("symbol_variation"), script_symbol_variation); ctx.setVariable(_("built_in_image"), script_built_in_image); + ctx.setVariable(_("import_image"), script_import_image); } From f9aa4f95772efbf0eba8ec941c4013d9c2bc6782 Mon Sep 17 00:00:00 2001 From: TomTkacz Date: Mon, 10 Mar 2025 20:34:23 -0500 Subject: [PATCH 02/10] fixed import_image not generating in CLI --- src/gfx/generated_image.hpp | 1 + src/script/functions/image.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gfx/generated_image.hpp b/src/gfx/generated_image.hpp index 42941923..f7023a9c 100644 --- a/src/gfx/generated_image.hpp +++ b/src/gfx/generated_image.hpp @@ -408,6 +408,7 @@ public: Image generate(const Options&) const override; bool operator == (const GeneratedImage& that) const override; inline String toString() { return filepath; } + inline String ExternalImage::toCode() const override { return ""; } private: String filepath; }; diff --git a/src/script/functions/image.cpp b/src/script/functions/image.cpp index 927d529b..f799faa6 100644 --- a/src/script/functions/image.cpp +++ b/src/script/functions/image.cpp @@ -19,6 +19,7 @@ #include #include #include +#include // for MSE_CLI void parse_enum(const String&, ImageCombine& out); @@ -45,8 +46,12 @@ SCRIPT_FUNCTION(to_card_image) { } SCRIPT_FUNCTION(import_image) { + SCRIPT_PARAM(Set*, set); SCRIPT_PARAM(String, path); - return make_intrusive(path); + auto extImg = make_intrusive(path); + if (cli.haveConsole()) // makes sure generate() is called, but only once, when using the CLI + extImg->generate(GeneratedImage::Options(0, 0, set->stylesheet.get(), set)); + return extImg; } // ----------------------------------------------------------------------------- : Image functions From 06f94bb50260b95e09d91119ae4c40cf671e5e66 Mon Sep 17 00:00:00 2001 From: TomTkacz Date: Tue, 11 Mar 2025 03:24:31 -0500 Subject: [PATCH 03/10] fixed duplicate set writing bug + enforced unicode strings --- src/gfx/generated_image.cpp | 12 ++++++++---- src/gfx/generated_image.hpp | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/gfx/generated_image.cpp b/src/gfx/generated_image.cpp index 5dc915b9..8c4686f2 100644 --- a/src/gfx/generated_image.cpp +++ b/src/gfx/generated_image.cpp @@ -522,6 +522,10 @@ bool ImageValueToImage::operator == (const GeneratedImage& that) const { Image ExternalImage::generate(const Options& opt) const { wxFileName fname(filepath, wxPATH_UNIX); + // has a pre-existing .mse-set file been loaded? + if (opt.local_package->needSaveAs()) + throw ScriptError(_("Cannot import an image without first saving/loading a set file.")); + // does the file pointed to by filepath exist? if (!fname.FileExists()) { String filePathString = fname.GetAbsolutePath().ToStdString(); @@ -542,19 +546,19 @@ Image ExternalImage::generate(const Options& opt) const { if (!opt.local_package->existsIn(fileNameNoExtension)) { auto outStream = opt.local_package->openOut(fileNameNoExtension); wxFileInputStream inStream = wxFileInputStream(filepath.ToStdString()); - if (!inStream.IsOk()) throw ScriptError("Failed to create file stream."); + if (!inStream.IsOk()) throw ScriptError(_("Failed to create file stream.")); outStream->Write(inStream); - if (!outStream->IsOk()) throw ScriptError("Failed to write image to set."); + if (!outStream->IsOk()) throw ScriptError(_("Failed to write image to set.")); outStream->Close(); } // save the package with the new image - opt.local_package->saveAs(opt.local_package->relativeFilename(), false, false); + opt.local_package->save(false); auto imageInputStream = opt.local_package->openIn(fileNameNoExtension); Image img(*imageInputStream.get(), bitmapType); - if (!img.IsOk()) throw ScriptError("The image could not be created."); + if (!img.IsOk()) throw ScriptError(_("The image could not be created.")); return img; } diff --git a/src/gfx/generated_image.hpp b/src/gfx/generated_image.hpp index f7023a9c..c679360a 100644 --- a/src/gfx/generated_image.hpp +++ b/src/gfx/generated_image.hpp @@ -408,7 +408,7 @@ public: Image generate(const Options&) const override; bool operator == (const GeneratedImage& that) const override; inline String toString() { return filepath; } - inline String ExternalImage::toCode() const override { return ""; } + inline String toCode() const override { return _(""); } private: String filepath; }; From e83233f5123164ae545f3a90f22d4da5994e8288 Mon Sep 17 00:00:00 2001 From: TomTkacz Date: Tue, 11 Mar 2025 03:30:17 -0500 Subject: [PATCH 04/10] removed unused include --- src/script/functions/construction.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/script/functions/construction.cpp b/src/script/functions/construction.cpp index 468bdd80..ac71dd23 100644 --- a/src/script/functions/construction.cpp +++ b/src/script/functions/construction.cpp @@ -18,7 +18,6 @@ #include #include #include -#include // ----------------------------------------------------------------------------- : new_card From 551efc70ca3a3bcf1c0f8490b8f7d9f820840efc Mon Sep 17 00:00:00 2001 From: TomTkacz Date: Wed, 12 Mar 2025 06:07:16 -0500 Subject: [PATCH 05/10] removed 'path:' prefix in function call --- src/script/functions/image.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/script/functions/image.cpp b/src/script/functions/image.cpp index f799faa6..6ae338f7 100644 --- a/src/script/functions/image.cpp +++ b/src/script/functions/image.cpp @@ -47,8 +47,8 @@ SCRIPT_FUNCTION(to_card_image) { SCRIPT_FUNCTION(import_image) { SCRIPT_PARAM(Set*, set); - SCRIPT_PARAM(String, path); - auto extImg = make_intrusive(path); + SCRIPT_PARAM(String, input); + auto extImg = make_intrusive(input); if (cli.haveConsole()) // makes sure generate() is called, but only once, when using the CLI extImg->generate(GeneratedImage::Options(0, 0, set->stylesheet.get(), set)); return extImg; From 4b43d976acf6218da2b40d277e5d8a296a010eba Mon Sep 17 00:00:00 2001 From: Tom Tkacz Date: Mon, 7 Apr 2025 14:23:54 -0500 Subject: [PATCH 06/10] Updated static windows build instructions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1a670e02..e514934f 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ On windows, the program can be compiled with Visual Studio (recommended) or with ======= ```` -.\vcpkg install pkgconf wxwidgets boost-smart-ptr boost-regex boost-logic boost-pool boost-iterator hunspell --triplet=x64-windows-static +.\vcpkg install pkgconf wxwidgets[fonts] boost-smart-ptr boost-regex boost-logic boost-pool boost-iterator hunspell --triplet=x64-windows-static ```` and/or ```` From 9c6d3a84efdf8107e78e0897fcc375f344b67c03 Mon Sep 17 00:00:00 2001 From: Tom Tkacz Date: Mon, 7 Apr 2025 14:26:40 -0500 Subject: [PATCH 07/10] Reverted build instruction (incorrect branch) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e514934f..1a670e02 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ On windows, the program can be compiled with Visual Studio (recommended) or with ======= ```` -.\vcpkg install pkgconf wxwidgets[fonts] boost-smart-ptr boost-regex boost-logic boost-pool boost-iterator hunspell --triplet=x64-windows-static +.\vcpkg install pkgconf wxwidgets boost-smart-ptr boost-regex boost-logic boost-pool boost-iterator hunspell --triplet=x64-windows-static ```` and/or ```` From cdfec5d00c99ff8d34034f289e613184602ba490 Mon Sep 17 00:00:00 2001 From: GenevensiS <66968533+G-e-n-e-v-e-n-s-i-S@users.noreply.github.com> Date: Thu, 10 Apr 2025 20:01:05 +0200 Subject: [PATCH 08/10] add docs --- doc/function/import_image.txt | 13 +++++++++++++ doc/function/index.txt | 1 + .../website/drupal/mse-drupal-modules/highlight.inc | 1 + 3 files changed, 15 insertions(+) create mode 100644 doc/function/import_image.txt diff --git a/doc/function/import_image.txt b/doc/function/import_image.txt new file mode 100644 index 00000000..f1eedab7 --- /dev/null +++ b/doc/function/import_image.txt @@ -0,0 +1,13 @@ +Function: import_image + +--Usage-- +> import_image(image_path) + +Load an image from outside the data folder. Intended for use from the CLI. + +--Parameters-- +! Parameter Type Description +| @input@ [[type:string]] Full path of the image to load + +--Examples-- +> import_image("D:/Art/Ajani.png") diff --git a/doc/function/index.txt b/doc/function/index.txt index 13ed7844..ca906790 100644 --- a/doc/function/index.txt +++ b/doc/function/index.txt @@ -93,6 +93,7 @@ These functions are built into the program, other [[type:function]]s can be defi | [[fun:rotate_image]] Rotate an image. | [[fun:drop_shadow]] Add a drop shadow to an image. | [[fun:symbol_variation]] Render a variation of a [[type:symbol]]. +| [[fun:import_image]] Load an image from outside the data folder. | [[fun:built_in_image]] Return an image built into the program. ! Cards <<< diff --git a/tools/website/drupal/mse-drupal-modules/highlight.inc b/tools/website/drupal/mse-drupal-modules/highlight.inc index 2c9f908d..984b3a4b 100644 --- a/tools/website/drupal/mse-drupal-modules/highlight.inc +++ b/tools/website/drupal/mse-drupal-modules/highlight.inc @@ -88,6 +88,7 @@ $built_in_functions = array( 'rotate' =>'', 'drop_shadow' =>'', 'symbol_variation' =>'', + 'import_image' =>'', 'built_in_image' =>'', // cards 'new_card' =>'', From 1a3940c16d24a207a5de7af5dd099a57bb190180 Mon Sep 17 00:00:00 2001 From: GenevensiS <66968533+G-e-n-e-v-e-n-s-i-S@users.noreply.github.com> Date: Fri, 11 Apr 2025 03:25:21 +0200 Subject: [PATCH 09/10] localization pattern --- data/en.mse-locale/locale | 7 +++++++ doc/function/import_image.txt | 2 +- src/gfx/generated_image.cpp | 28 +++++++++++----------------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/data/en.mse-locale/locale b/data/en.mse-locale/locale index dbe12600..e9f42fa5 100644 --- a/data/en.mse-locale/locale +++ b/data/en.mse-locale/locale @@ -803,6 +803,13 @@ error: To resolve this, add: depends on: %s %s + # Image import + import not found: File not found: '%s' + can't import image without set: Must first save or load a set file before importing file: '%s' + can't create file stream: Failed to create file stream: '%s' + can't write image to set: Failed to write image to set: '%s' + can't import image: Failed to import image: '%s' + # Script stuff has no member: %s has no member '%s' can't convert: Can't convert from %s to %s diff --git a/doc/function/import_image.txt b/doc/function/import_image.txt index f1eedab7..874fab5a 100644 --- a/doc/function/import_image.txt +++ b/doc/function/import_image.txt @@ -10,4 +10,4 @@ Load an image from outside the data folder. Intended for use from the CLI. | @input@ [[type:string]] Full path of the image to load --Examples-- -> import_image("D:/Art/Ajani.png") +> new_card([image: import_image("D:/Art/Ajani.png"), card_color: "green"]) diff --git a/src/gfx/generated_image.cpp b/src/gfx/generated_image.cpp index 8c4686f2..d77daaa6 100644 --- a/src/gfx/generated_image.cpp +++ b/src/gfx/generated_image.cpp @@ -521,34 +521,28 @@ bool ImageValueToImage::operator == (const GeneratedImage& that) const { Image ExternalImage::generate(const Options& opt) const { wxFileName fname(filepath, wxPATH_UNIX); - - // has a pre-existing .mse-set file been loaded? - if (opt.local_package->needSaveAs()) - throw ScriptError(_("Cannot import an image without first saving/loading a set file.")); + String filePathString = fname.GetAbsolutePath(); + + // has a pre-existing .mse-set file been loaded? + if (opt.local_package->needSaveAs()) throw ScriptError(_ERROR_1_("can't import image without set", filePathString)); // does the file pointed to by filepath exist? - if (!fname.FileExists()) { - String filePathString = fname.GetAbsolutePath().ToStdString(); - throw ScriptError(format_string(_("The file '%s' was not found."),filePathString)); - } + if (!fname.FileExists()) throw ScriptError(_ERROR_1_("import not found", filePathString)); String fileExt = fname.GetExt(); wxBitmapType bitmapType; - if (fileExt == _("png")) - bitmapType = wxBITMAP_TYPE_PNG; - else if (fileExt == _("jpg")) - bitmapType = wxBITMAP_TYPE_JPEG; - else - bitmapType = wxBITMAP_TYPE_BMP; + if (fileExt == _("png")) bitmapType = wxBITMAP_TYPE_PNG; + else if (fileExt == _("jpg") || fileExt == _("jpeg")) bitmapType = wxBITMAP_TYPE_JPEG; + else bitmapType = wxBITMAP_TYPE_BMP; // does the file exist in the package? String fileNameNoExtension = fname.GetName(); if (!opt.local_package->existsIn(fileNameNoExtension)) { auto outStream = opt.local_package->openOut(fileNameNoExtension); wxFileInputStream inStream = wxFileInputStream(filepath.ToStdString()); - if (!inStream.IsOk()) throw ScriptError(_("Failed to create file stream.")); + if (!inStream.IsOk()) throw ScriptError(_ERROR_1_("can't create file stream", filePathString)); outStream->Write(inStream); - if (!outStream->IsOk()) throw ScriptError(_("Failed to write image to set.")); + if (!outStream->IsOk()) throw ScriptError(_ERROR_1_("can't write image to set", filePathString)); outStream->Close(); } @@ -558,7 +552,7 @@ Image ExternalImage::generate(const Options& opt) const { auto imageInputStream = opt.local_package->openIn(fileNameNoExtension); Image img(*imageInputStream.get(), bitmapType); - if (!img.IsOk()) throw ScriptError(_("The image could not be created.")); + if (!img.IsOk()) throw ScriptError(_ERROR_1_("can't import image", filePathString)); return img; } From 91433d5c9d112619f9d9f1a310a1f76d86787351 Mon Sep 17 00:00:00 2001 From: GenevensiS <66968533+G-e-n-e-v-e-n-s-i-S@users.noreply.github.com> Date: Fri, 11 Apr 2025 03:48:18 +0200 Subject: [PATCH 10/10] localize pattern in new_card --- data/en.mse-locale/locale | 4 ++++ src/script/functions/construction.cpp | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/data/en.mse-locale/locale b/data/en.mse-locale/locale index e9f42fa5..e98ccb86 100644 --- a/data/en.mse-locale/locale +++ b/data/en.mse-locale/locale @@ -810,6 +810,10 @@ error: can't write image to set: Failed to write image to set: '%s' can't import image: Failed to import image: '%s' + # Card creation + no field with name: Card doesn't have a field named '%s' + can't set value: Can not set card value '%s', it is not of the right type + # Script stuff has no member: %s has no member '%s' can't convert: Can't convert from %s to %s diff --git a/src/script/functions/construction.cpp b/src/script/functions/construction.cpp index ac71dd23..e96cd034 100644 --- a/src/script/functions/construction.cpp +++ b/src/script/functions/construction.cpp @@ -34,7 +34,7 @@ SCRIPT_FUNCTION(new_card) { // find value to update IndexMap::const_iterator value_it = new_card->data.find(name); if (value_it == new_card->data.end()) { - throw ScriptError(format_string(_("Card doesn't have a field named '%s'"),name)); + throw ScriptError(_ERROR_1_("no field with name", name)); } Value* value = value_it->get(); // set the value @@ -50,7 +50,7 @@ SCRIPT_FUNCTION(new_card) { wxFileName fname( static_cast(v.get())->toString() ); ivalue->filename = LocalFileName::fromReadString( fname.GetName(), ""); } else { - throw ScriptError(format_string(_("Can not set value '%s', it is not of the right type"),name)); + throw ScriptError(_ERROR_1_("can't set value", name)); } } SCRIPT_RETURN(new_card);