allow import_image to accept script images
import_image and download_image no longer save the set or require it to have been saved once
console panel now tries to output toJson() before falling back to toCode()
This commit is contained in:
GenevensiS
2026-05-14 13:50:02 +02:00
parent 6f4fc0066d
commit 76af996f0a
9 changed files with 78 additions and 40 deletions
+3 -2
View File
@@ -224,10 +224,11 @@ void Set::validate(Version file_app_version) {
// update cards with stylesheet update_cards_scripts
for (int i = 0; i < cards.size(); ++i) {
CardP& card = cards[i];
StyleSheetP stylesheet = stylesheetForP(card);
StyleSheetP stylesheet = card->stylesheet ? card->stylesheet : stylesheetForP(card);
Version stylesheet_version = card->stylesheet_version.isZero() ? this->stylesheet_version : card->stylesheet_version;
for (int j = 0; j < stylesheet->update_cards_scripts.size(); ++j) {
UpdateCardsScriptP& script = stylesheet->update_cards_scripts[j];
if (card->stylesheet_version >= script->before_version) continue;
if (stylesheet_version >= script->before_version) continue;
vector<CardP> new_cards = script->perform(*this, card);
if (!new_cards.empty()) {
FOR_EACH(new_card, new_cards) {
+40 -25
View File
@@ -783,16 +783,39 @@ bool SetMetadataImage::operator == (const GeneratedImage& that) const {
&& metadata == that2->metadata;
}
// ----------------------------------------------------------------------------- : ScriptedImage
ScriptedImage::ScriptedImage(Set* set, const GeneratedImageP& image) {
// get the image
Image img = image->generate(GeneratedImage::Options(0, 0, set, set));
// add the file to the set
LocalFileName new_image_file = set->newFileName(_("scripted_image"), _(".png"));
savename = new_image_file.toStringForWriting();
loadpath = savename;
img.SaveFile(set->nameOut(new_image_file), wxBITMAP_TYPE_PNG);
}
Image ScriptedImage::generate(const Options& opt) {
auto imageInputStream = opt.local_package->openIn(savename);
Image img(*imageInputStream, wxBITMAP_TYPE_PNG);
if (!img.IsOk()) throw ScriptError(_ERROR_1_("can't import image", loadpath));
return img;
}
bool ScriptedImage::operator == (const GeneratedImage& that) const {
const ScriptedImage* that2 = dynamic_cast<const ScriptedImage*>(&that);
return that2 && that2->loadpath == loadpath;
}
// ----------------------------------------------------------------------------- : ImportedImage
ImportedImage::ImportedImage(Set* set, const String& filepath)
{
// has the set already been saved at least once?
if (set->needSaveAs()) throw ScriptError(_ERROR_1_("can't import image without set", filepath));
ImportedImage::ImportedImage(Set* set, const String& filepath) {
// determine save name
loadpath = filepath;
savename = normalize_internal_filename(loadpath + _(".png"));
savename = normalize_internal_filename(loadpath);
savename.Replace(":", "-");
savename.Replace("/", "-");
@@ -801,18 +824,16 @@ ImportedImage::ImportedImage(Set* set, const String& filepath)
if (set->contains(savename)) return;
else throw ScriptError(_ERROR_1_("import not found", loadpath));
}
// is the file an image?
Image img;
img.LoadFile(loadpath);
if (!img.IsOk()) throw ScriptError(_ERROR_1_("import not image", loadpath));
// add the file to the set (or overwrite it if pre-existing), save set
auto outStream = set->openOut(savename);
img.SaveFile(*outStream, wxBITMAP_TYPE_PNG);
if (!outStream->IsOk()) throw ScriptError(_ERROR_1_("can't write image to set", loadpath));
outStream->Close();
set->save(false);
// add the file to the set
LocalFileName new_image_file = set->newFileName(savename, _(".png"));
savename = new_image_file.toStringForWriting();
img.SaveFile(set->nameOut(new_image_file), wxBITMAP_TYPE_PNG);
}
Image ImportedImage::generate(const Options& opt) {
@@ -831,14 +852,10 @@ bool ImportedImage::operator == (const GeneratedImage& that) const {
// ----------------------------------------------------------------------------- : DownloadedImage
DownloadedImage::DownloadedImage(Set* set, const String& url)
{
// has the set already been saved at least once?
if (set->needSaveAs()) throw ScriptError(_ERROR_1_("can't download image without set", url));
DownloadedImage::DownloadedImage(Set* set, const String& url) {
// determine save name
loadpath = url;
savename = normalize_internal_filename(loadpath + _(".png"));
savename = normalize_internal_filename(loadpath);
savename.Replace(":", "-");
savename.Replace("/", "-");
@@ -852,12 +869,10 @@ DownloadedImage::DownloadedImage(Set* set, const String& url)
// is the data an image?
if (!wnd.content_type.StartsWith(_("image/"))) throw ScriptError(_ERROR_1_("download not image", loadpath));
// add the file to the set (or overwrite it if pre-existing), save set
auto outStream = set->openOut(savename);
wnd.image_out.SaveFile(*outStream, wxBITMAP_TYPE_PNG);
if (!outStream->IsOk()) throw ScriptError(_ERROR_1_("can't write image to set", loadpath));
outStream->Close();
set->save(false);
// add the file to the set
LocalFileName new_image_file = set->newFileName(savename, _(".png"));
savename = new_image_file.toStringForWriting();
wnd.image_out.SaveFile(set->nameOut(new_image_file), wxBITMAP_TYPE_PNG);
}
Image DownloadedImage::generate(const Options& opt) {
+10
View File
@@ -522,6 +522,16 @@ protected:
String savename;
};
// ----------------------------------------------------------------------------- : ScriptedImage
/// Load an image from a script
class ScriptedImage : public ExternalImage {
public:
ScriptedImage(Set* set, const GeneratedImageP& image);
Image generate(const Options&) override;
bool operator == (const GeneratedImage& that) const override;
};
// ----------------------------------------------------------------------------- : ImportedImage
/// Load an image from the filesystem
+6 -3
View File
@@ -14,6 +14,7 @@
#include <util/window_id.hpp>
#include <data/stylesheet.hpp>
#include <data/card.hpp>
#include <script/functions/json.hpp>
#include <wx/splitter.h>
#include <wx/dcbuffer.h>
#include <wx/clipbrd.h>
@@ -624,7 +625,7 @@ void ConsolePanel::exec(String const& command) {
// type of result
ScriptType type = result->type();
if (type == SCRIPT_IMAGE) {
GeneratedImage::Options options(0,0, set->stylesheet.get(), set.get());
GeneratedImage::Options options(0,0, card->stylesheet ? card->stylesheet.get() : set->stylesheet.get(), set.get());
wxImage image = result->toImage()->generate(options);
message->bitmap = wxBitmap(image);
} else if (type == SCRIPT_COLOR) {
@@ -634,8 +635,10 @@ void ConsolePanel::exec(String const& command) {
fill_image(image,color);
set_alpha(image, color.Alpha() / 255.0);
message->bitmap = wxBitmap(image);
} else {
message->text = result->toCode();
} else {
boost::json::value jresult = mse_to_json(result, set.get(), true);
if (jresult.is_null()) message->text = result->toCode();
else message->text = json_pretty_print(jresult);
}
messages->add_message(message);
} catch (ScriptError const& e) {
@@ -62,6 +62,8 @@ inline static void set_container(Value* container, ScriptValueP& value, String k
cvalue->value = value->toString();
}
else if (PackageChoiceValue* pvalue = dynamic_cast<PackageChoiceValue*>(container)) {
String package_name = value->toString();
while (package_name.starts_with(_("/"))) package_name = package_name.substr(1);
pvalue->package_name = value->toString();
}
else if (ColorValue* cvalue = dynamic_cast<ColorValue*>(container)) {
+12 -6
View File
@@ -51,9 +51,15 @@ SCRIPT_FUNCTION(to_card_image) {
}
SCRIPT_FUNCTION(import_image) {
SCRIPT_PARAM(Set*, set);
SCRIPT_PARAM(String, input);
return make_intrusive<ImportedImage>(set, input);
SCRIPT_PARAM(Set*, set);
SCRIPT_PARAM_C(ScriptValueP, input);
if (input->type() == SCRIPT_IMAGE) {
return make_intrusive<ScriptedImage>(set, input->toImage());
}
else if (input->type() == SCRIPT_STRING) {
return make_intrusive<ImportedImage>(set, input->toString());
}
throw ScriptErrorConversion(input->typeName(), _TYPE_("image"));
}
SCRIPT_FUNCTION(download_image) {
@@ -67,9 +73,9 @@ SCRIPT_FUNCTION(download_image) {
SCRIPT_FUNCTION(get_metadata) {
SCRIPT_PARAM(Set*, set);
SCRIPT_PARAM(GeneratedImageP, input);
Image img = input->generate(GeneratedImage::Options(0, 0, set));
SCRIPT_RETURN(img.GetOption(wxIMAGE_OPTION_PNG_DESCRIPTION));
SCRIPT_PARAM(GeneratedImageP, input);
Image image = input->generate(GeneratedImage::Options(0, 0, set, set));
SCRIPT_RETURN(image.GetOption(wxIMAGE_OPTION_PNG_DESCRIPTION));
}
SCRIPT_FUNCTION(set_metadata) {
+2 -2
View File
@@ -872,7 +872,7 @@ boost::json::object mse_to_json(const IndexMap<FieldP, ValueP>& map) {
return indexmapv;
}
boost::json::value mse_to_json(const ScriptValueP& sv, Set* set) {
boost::json::value mse_to_json(const ScriptValueP& sv, Set* set, bool suppress_warnings) {
// special types
if (ScriptObject<PackItemP>* o = dynamic_cast<ScriptObject<PackItemP>*> (sv.get())) return mse_to_json( o->getValue());
if (ScriptObject<PackTypeP>* o = dynamic_cast<ScriptObject<PackTypeP>*> (sv.get())) return mse_to_json( o->getValue());
@@ -936,6 +936,6 @@ boost::json::value mse_to_json(const ScriptValueP& sv, Set* set) {
}
}
}
queue_message(MESSAGE_ERROR, _ERROR_1_("json unknown script type", sv->typeName()));
if (!suppress_warnings) queue_message(MESSAGE_WARNING, _ERROR_1_("json unknown script type", sv->typeName()));
return boost::json::value(nullptr);
}
+1 -1
View File
@@ -72,4 +72,4 @@ boost::json::object mse_to_json(const Set* set);
boost::json::object mse_to_json(const IndexMap<FieldP,ValueP>& map);
boost::json::value mse_to_json(const ScriptValueP& sv, Set* set);
boost::json::value mse_to_json(const ScriptValueP& sv, Set* set, bool suppress_warnings = false);
+2 -1
View File
@@ -30,7 +30,8 @@ String Version::toString() const {
}
}
Version Version::fromString(const String& version) {
Version Version::fromString(const String& version) {
if (version.empty()) return Version();
UInt major = 0, minor = 0, revision = 0;
if (wxSscanf(version, _("%u.%u.%u"), &major, &minor, &revision)<=1) // a.b.c style
wxSscanf(version, _("%u-%u-%u"), &major, &minor, &revision); // date style