mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
add download_image, refactor import_image
This commit is contained in:
+78
-43
@@ -10,10 +10,12 @@
|
||||
#include <gfx/generated_image.hpp>
|
||||
#include <util/io/package.hpp>
|
||||
#include <util/error.hpp>
|
||||
#include <data/set.hpp>
|
||||
#include <data/symbol.hpp>
|
||||
#include <data/field/symbol.hpp>
|
||||
#include <render/symbol/filter.hpp>
|
||||
#include <gui/util.hpp> // load_resource_image
|
||||
#include <gui/web_request_window.hpp>
|
||||
#include <wx/wfstream.h>
|
||||
|
||||
// ----------------------------------------------------------------------------- : GeneratedImage
|
||||
@@ -673,55 +675,88 @@ bool ImageValueToImage::operator == (const GeneratedImage& that) const {
|
||||
&& age == that2->age;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : ExternalImage
|
||||
|
||||
ExternalImage::ExternalImage(const String& filepath)
|
||||
: filepath(filepath), loaded(false)
|
||||
{
|
||||
filepathSanitized = filepath;
|
||||
filepathSanitized.Replace(":", "-");
|
||||
filepathSanitized.Replace("\\", "-");
|
||||
filepathSanitized.Replace("/", "-");
|
||||
}
|
||||
// ----------------------------------------------------------------------------- : ImportedImage
|
||||
|
||||
Image ExternalImage::generate(const Options& opt) {
|
||||
// has a pre-existing .mse-set file been loaded?
|
||||
if (opt.local_package->needSaveAs()) throw ScriptError(_ERROR_1_("can't import image without set", filepath));
|
||||
ImportedImage::ImportedImage(Set* set, const String& filepath)
|
||||
{
|
||||
loadpath = filepath;
|
||||
|
||||
// has the set already been saved at least once?
|
||||
if (set->needSaveAs()) throw ScriptError(_ERROR_1_("can't import image without set", loadpath));
|
||||
|
||||
// does the file pointed to by filepath exist?
|
||||
wxFileName fname(filepath, wxPATH_UNIX);
|
||||
if (!fname.FileExists()) throw ScriptError(_ERROR_1_("import not found", filepath));
|
||||
|
||||
// add the file to the package (or overwrite it if pre-existing)
|
||||
if (!loaded || !opt.local_package->existsIn(filepathSanitized)) {
|
||||
auto outStream = opt.local_package->openOut(filepathSanitized);
|
||||
wxFileInputStream inStream(filepath);
|
||||
if (!inStream.IsOk()) throw ScriptError(_ERROR_1_("can't create file stream", filepath));
|
||||
outStream->Write(inStream);
|
||||
if (!outStream->IsOk()) throw ScriptError(_ERROR_1_("can't write image to set", filepath));
|
||||
outStream->Close();
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
// save the package with the new image
|
||||
opt.local_package->save(false);
|
||||
if (!wxFileName(loadpath, wxPATH_UNIX).FileExists()) throw ScriptError(_ERROR_1_("import not found", loadpath));
|
||||
|
||||
// generate Image
|
||||
String fileExt = fname.GetExt();
|
||||
wxBitmapType bitmapType;
|
||||
if (fileExt == _("png")) bitmapType = wxBITMAP_TYPE_PNG;
|
||||
else if (fileExt == _("jpg") || fileExt == _("jpeg")) bitmapType = wxBITMAP_TYPE_JPEG;
|
||||
else bitmapType = wxBITMAP_TYPE_BMP;
|
||||
// is the file an image?
|
||||
Image img;
|
||||
img.LoadFile(loadpath);
|
||||
if (!img.IsOk()) throw ScriptError(_ERROR_1_("import not image", loadpath));
|
||||
|
||||
auto imageInputStream = opt.local_package->openIn(filepathSanitized);
|
||||
Image img(*imageInputStream, bitmapType);
|
||||
// add the file to the set (or overwrite it if pre-existing), save set
|
||||
savename = normalize_internal_filename(loadpath);
|
||||
savename.Replace(":", "-");
|
||||
savename.Replace("/", "-");
|
||||
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);
|
||||
}
|
||||
|
||||
if (!img.IsOk()) throw ScriptError(_ERROR_1_("can't import image", filepath));
|
||||
Image ImportedImage::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 ExternalImage::operator == (const GeneratedImage& that) const {
|
||||
const ExternalImage* that2 = dynamic_cast<const ExternalImage*>(&that);
|
||||
return that2 && that2->filepath == filepath;
|
||||
}
|
||||
|
||||
bool ImportedImage::operator == (const GeneratedImage& that) const {
|
||||
const ImportedImage* that2 = dynamic_cast<const ImportedImage*>(&that);
|
||||
return that2 && that2->loadpath == loadpath;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : DownloadedImage
|
||||
|
||||
DownloadedImage::DownloadedImage(Set* set, const String& url)
|
||||
{
|
||||
loadpath = url;
|
||||
|
||||
// has the set already been saved at least once?
|
||||
if (set->needSaveAs()) throw ScriptError(_ERROR_1_("can't download image without set", loadpath));
|
||||
|
||||
// can we download the data?
|
||||
WebRequestWindow wnd(loadpath);
|
||||
if (wnd.ShowModal() != wxID_OK) throw ScriptError(_ERROR_1_("can't download image", loadpath));
|
||||
|
||||
// is the data an image?
|
||||
const String& content_type = wnd.out.GetContentType();
|
||||
if (!content_type.StartsWith(_("image"))) throw ScriptError(_ERROR_1_("download not image", loadpath));
|
||||
Image img(*wnd.out.GetStream());
|
||||
if (!img.IsOk()) throw ScriptError(_ERROR_("web request corrupted"));
|
||||
|
||||
// add the file to the set (or overwrite it if pre-existing), save set
|
||||
savename = normalize_internal_filename(loadpath);
|
||||
savename.Replace(":", "-");
|
||||
savename.Replace("/", "-");
|
||||
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);
|
||||
}
|
||||
|
||||
Image DownloadedImage::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 download image", loadpath));
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
bool DownloadedImage::operator == (const GeneratedImage& that) const {
|
||||
const DownloadedImage* that2 = dynamic_cast<const DownloadedImage*>(&that);
|
||||
return that2 && that2->loadpath == loadpath;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
DECLARE_POINTER_TYPE(GeneratedImage);
|
||||
DECLARE_POINTER_TYPE(SymbolVariation);
|
||||
class Package;
|
||||
class Set;
|
||||
|
||||
// ----------------------------------------------------------------------------- : GeneratedImage
|
||||
|
||||
@@ -450,16 +451,33 @@ private:
|
||||
|
||||
// ----------------------------------------------------------------------------- : ExternalImage
|
||||
|
||||
/// Load an image from the filesystem
|
||||
/// Load an image from outside the data folder
|
||||
class ExternalImage : public GeneratedImage {
|
||||
public:
|
||||
ExternalImage(const String& filepath);
|
||||
inline String toString() { return savename; }
|
||||
inline String toCode() const override { return _("<image>"); }
|
||||
|
||||
protected:
|
||||
String loadpath;
|
||||
String savename;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : ImportedImage
|
||||
|
||||
/// Load an image from the filesystem
|
||||
class ImportedImage : public ExternalImage {
|
||||
public:
|
||||
ImportedImage(Set* set, const String& filepath);
|
||||
Image generate(const Options&) override;
|
||||
bool operator == (const GeneratedImage& that) const override;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : DownloadedImage
|
||||
|
||||
/// Load an image from the internet
|
||||
class DownloadedImage : public ExternalImage {
|
||||
public:
|
||||
DownloadedImage(Set* set, const String& url);
|
||||
Image generate(const Options&) override;
|
||||
bool operator == (const GeneratedImage& that) const override;
|
||||
inline String toString() { return filepath; }
|
||||
inline String toCode() const override { return _("<image>"); }
|
||||
private:
|
||||
String filepath;
|
||||
String filepathSanitized;
|
||||
bool loaded; ///< Make sure we at least load the image from outside the package once, as it may have been updated externally
|
||||
};
|
||||
|
||||
@@ -297,21 +297,23 @@ void BulkModificationWindow::onOk(wxCommandEvent&) {
|
||||
else if (dynamic_cast<ImageValue*>(values.front())) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
ImageValue* value = dynamic_cast<ImageValue*>(values[i]);
|
||||
wxFileName fname(static_cast<ExternalImage*>(new_values[i].get())->toString());
|
||||
ImageValue::ValueType new_value = LocalFileName::fromReadString(fname.GetName(), "");
|
||||
shared_ptr<SimpleValueAction<ImageValue, false>> action = make_shared<SimpleValueAction<ImageValue, false>>(value, new_value);
|
||||
action->setCard(cards[i]);
|
||||
actions.push_back(action);
|
||||
if (ExternalImage* img = dynamic_cast<ExternalImage*>(new_values[i].get())) {
|
||||
ImageValue::ValueType new_value = LocalFileName::fromReadString(img->toString(), "");
|
||||
shared_ptr<SimpleValueAction<ImageValue, false>> action = make_shared<SimpleValueAction<ImageValue, false>>(value, new_value);
|
||||
action->setCard(cards[i]);
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<SymbolValue*>(values.front())) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
SymbolValue* value = dynamic_cast<SymbolValue*>(values[i]);
|
||||
wxFileName fname(static_cast<ExternalImage*>(new_values[i].get())->toString());
|
||||
SymbolValue::ValueType new_value = LocalFileName::fromReadString(fname.GetName(), "");
|
||||
shared_ptr<SimpleValueAction<SymbolValue, false>> action = make_shared<SimpleValueAction<SymbolValue, false>>(value, new_value);
|
||||
action->setCard(cards[i]);
|
||||
actions.push_back(action);
|
||||
if (ExternalImage* img = dynamic_cast<ExternalImage*>(new_values[i].get())) {
|
||||
SymbolValue::ValueType new_value = LocalFileName::fromReadString(img->toString(), "");
|
||||
shared_ptr<SimpleValueAction<SymbolValue, false>> action = make_shared<SimpleValueAction<SymbolValue, false>>(value, new_value);
|
||||
action->setCard(cards[i]);
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -250,7 +250,7 @@ bool CardListBase::parseUrl(String& url, vector<CardP>& out) {
|
||||
}
|
||||
if (!url.StartsWith(_("http"))) return false;
|
||||
|
||||
WebRequestWindow wnd(this, url);
|
||||
WebRequestWindow wnd(url);
|
||||
if (wnd.ShowModal() == wxID_OK) {
|
||||
const String& content_type = wnd.out.GetContentType();
|
||||
if (content_type.StartsWith(_("image"))) {
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
|
||||
// ----------------------------------------------------------------------------- : WebRequestWindow
|
||||
|
||||
WebRequestWindow::WebRequestWindow(Window* parent, const String& url, bool sizer)
|
||||
: wxDialog(parent, wxID_ANY, _TITLE_("web request"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
WebRequestWindow::WebRequestWindow(const String& url, bool sizer)
|
||||
: wxDialog(wxTheApp->GetTopWindow(), wxID_ANY, _TITLE_("web request"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
{
|
||||
// init controls
|
||||
info = new wxStaticText(this, -1, _LABEL_("web request address"));
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
/// A window for displaying the progression of a WebRequest and returning the WebResponse
|
||||
class WebRequestWindow : public wxDialog {
|
||||
public:
|
||||
WebRequestWindow(Window* parent, const String& url, bool sizer=true);
|
||||
WebRequestWindow(const String& url, bool sizer=true);
|
||||
|
||||
wxWebResponse out;
|
||||
|
||||
|
||||
@@ -68,9 +68,8 @@ inline static void set_container(Value* container, ScriptValueP& value, String k
|
||||
cvalue->value = value->toColor();
|
||||
}
|
||||
else if (ImageValue* ivalue = dynamic_cast<ImageValue*>(container)) {
|
||||
if (ExternalImage* image = dynamic_cast<ExternalImage*>(value.get())) {
|
||||
wxFileName fname(image->toString());
|
||||
ivalue->filename = LocalFileName::fromReadString(fname.GetName(), "");
|
||||
if (ExternalImage* img = dynamic_cast<ExternalImage*>(value.get())) {
|
||||
ivalue->filename = LocalFileName::fromReadString(img->toString(), "");
|
||||
} else if (value->type() == SCRIPT_STRING) {
|
||||
ivalue->filename = LocalFileName::fromReadString(value->toString(), "");
|
||||
} else {
|
||||
@@ -105,15 +104,15 @@ inline static bool set_stylesheet_container(const Game& game, CardP& card, Scrip
|
||||
inline static bool set_builtin_container(const Game& game, CardP& card, ScriptValueP& value, String key_name, bool ignore_field_not_found) {
|
||||
// check if the given value is for a built-in field, if found set it and return true
|
||||
key_name = unified_form(key_name);
|
||||
if (key_name == _("notes") || key_name == _("note")) {
|
||||
if (key_name == _("card_notes") || key_name == _("notes") || key_name == _("note")) {
|
||||
card->notes = value->toString();
|
||||
return true;
|
||||
}
|
||||
else if (key_name == _("id") || key_name == _("uid")) {
|
||||
else if (key_name == _("id") || key_name == _("uid") || key_name == _("uuid")) {
|
||||
card->uid = value->toString();
|
||||
return true;
|
||||
}
|
||||
else if (key_name == _("linked_card") || key_name == _("linked_card_1")) {
|
||||
else if (key_name == _("linked_card_1") || key_name == _("linked_card")) {
|
||||
card->linked_card_1 = value->toString();
|
||||
return true;
|
||||
}
|
||||
@@ -129,7 +128,7 @@ inline static bool set_builtin_container(const Game& game, CardP& card, ScriptVa
|
||||
card->linked_card_4 = value->toString();
|
||||
return true;
|
||||
}
|
||||
else if (key_name == _("linked_relation") || key_name == _("linked_relation_1")) {
|
||||
else if (key_name == _("linked_relation_1") || key_name == _("linked_relation")) {
|
||||
card->linked_relation_1 = value->toString();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <data/format/formats.hpp>
|
||||
#include <gfx/generated_image.hpp>
|
||||
#include <render/symbol/filter.hpp>
|
||||
#include <cli/text_io_handler.hpp> // for MSE_CLI
|
||||
|
||||
void parse_enum(const String&, ImageCombine& out);
|
||||
|
||||
@@ -54,10 +53,13 @@ SCRIPT_FUNCTION(to_card_image) {
|
||||
SCRIPT_FUNCTION(import_image) {
|
||||
SCRIPT_PARAM(Set*, set);
|
||||
SCRIPT_PARAM(String, input);
|
||||
auto extImg = make_intrusive<ExternalImage>(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;
|
||||
return make_intrusive<ImportedImage>(set, input);
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(download_image) {
|
||||
SCRIPT_PARAM(Set*, set);
|
||||
SCRIPT_PARAM(String, input);
|
||||
return make_intrusive<DownloadedImage>(set, input);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Image functions
|
||||
@@ -316,4 +318,5 @@ void init_script_image_functions(Context& ctx) {
|
||||
ctx.setVariable(_("symbol_variation"), script_symbol_variation);
|
||||
ctx.setVariable(_("built_in_image"), script_built_in_image);
|
||||
ctx.setVariable(_("import_image"), script_import_image);
|
||||
ctx.setVariable(_("download_image"), script_download_image);
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ public:
|
||||
|
||||
// ----------------------------------------------------------------------------- : Package : inside
|
||||
|
||||
bool Package::existsIn(const String& file) {
|
||||
bool Package::contains(const String& file) {
|
||||
FileInfos::iterator it = files.find(normalize_internal_filename(file));
|
||||
if (it == files.end()) {
|
||||
// does it look like a relative filename?
|
||||
@@ -650,11 +650,11 @@ void Packaged::loadFully() {
|
||||
}
|
||||
}
|
||||
|
||||
void Packaged::save() {
|
||||
void Packaged::save(bool remove_unused) {
|
||||
WITH_DYNAMIC_ARG(writing_package, this);
|
||||
writeFile(typeName(), *this, fileVersion());
|
||||
referenceFile(typeName());
|
||||
Package::save();
|
||||
Package::save(remove_unused);
|
||||
}
|
||||
void Packaged::saveAs(const String& package, bool remove_unused, bool as_directory) {
|
||||
WITH_DYNAMIC_ARG(writing_package, this);
|
||||
|
||||
@@ -178,15 +178,15 @@ public:
|
||||
// --------------------------------------------------- : Managing the inside of the package
|
||||
|
||||
/// Check if a file is in the package.
|
||||
bool existsIn(const String& file);
|
||||
inline bool existsIn(const LocalFileName& file) {
|
||||
return existsIn(file.fn);
|
||||
bool contains(const String& file);
|
||||
inline bool contains(const LocalFileName& file) {
|
||||
return contains(file.fn);
|
||||
}
|
||||
|
||||
/// Open an input stream for a file in the package.
|
||||
unique_ptr<wxInputStream> openIn(const String& file);
|
||||
inline unique_ptr<wxInputStream> openIn(const LocalFileName& file) {
|
||||
return openIn(file.fn);
|
||||
return openIn(file.fn);
|
||||
}
|
||||
|
||||
/// Open an output stream for a file in the package.
|
||||
@@ -331,7 +331,7 @@ public:
|
||||
void open(const String& package, bool just_header = false);
|
||||
/// Ensure the package is fully loaded.
|
||||
void loadFully();
|
||||
void save();
|
||||
void save(bool remove_unused = true);
|
||||
void saveAs(const String& package, bool remove_unused = true, bool as_directory = false);
|
||||
void saveCopy(const String& package);
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ bool PackageManager::existsInPackage(const String& name) {
|
||||
if (start < pos && pos != String::npos) {
|
||||
// open package
|
||||
PackagedP p = openAny(name.substr(start, pos - start));
|
||||
return p->existsIn(name.substr(pos + 1));
|
||||
return p->contains(name.substr(pos + 1));
|
||||
}
|
||||
}
|
||||
throw FileNotFoundError(name, _("No package name specified, use '/package/filename'"));
|
||||
|
||||
Reference in New Issue
Block a user