Convert SaveFileBaseCommand to CommandWithNewParams

With this patch we fixed some use cases:
* We can show the ui with a default filename { filename=..., ui=true }
* We can specify fromFrame/toFrame for SaveFileCopyAs
This commit is contained in:
David Capello 2022-06-13 17:04:12 -03:00
parent d160fb8b91
commit ddc1b76214
6 changed files with 80 additions and 58 deletions

View File

@ -86,24 +86,18 @@ private:
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
SaveFileBaseCommand::SaveFileBaseCommand(const char* id, CommandFlags flags) SaveFileBaseCommand::SaveFileBaseCommand(const char* id, CommandFlags flags)
: Command(id, flags) : CommandWithNewParams<SaveFileParams>(id, flags)
{ {
m_useUI = true;
m_ignoreEmpty = false;
} }
void SaveFileBaseCommand::onLoadParams(const Params& params) void SaveFileBaseCommand::onLoadParams(const Params& params)
{ {
m_filename = params.get("filename"); CommandWithNewParams<SaveFileParams>::onLoadParams(params);
m_filenameFormat = params.get("filename-format");
m_tag = params.get("frame-tag");
m_aniDir = params.get("ani-dir");
m_slice = params.get("slice");
if (params.has_param("from-frame") || if (this->params().fromFrame.isSet() ||
params.has_param("to-frame")) { this->params().toFrame.isSet()) {
doc::frame_t fromFrame = params.get_as<doc::frame_t>("from-frame"); doc::frame_t fromFrame = this->params().fromFrame();
doc::frame_t toFrame = params.get_as<doc::frame_t>("to-frame"); doc::frame_t toFrame = this->params().toFrame();
m_selFrames.insert(fromFrame, toFrame); m_selFrames.insert(fromFrame, toFrame);
m_adjustFramesByTag = true; m_adjustFramesByTag = true;
} }
@ -111,11 +105,6 @@ void SaveFileBaseCommand::onLoadParams(const Params& params)
m_selFrames.clear(); m_selFrames.clear();
m_adjustFramesByTag = false; m_adjustFramesByTag = false;
} }
std::string useUI = params.get("useUI");
m_useUI = (useUI.empty() || (useUI == "true"));
m_ignoreEmpty = params.get_as<bool>("ignoreEmpty");
} }
// Returns true if there is a current sprite to save. // Returns true if there is a current sprite to save.
@ -141,19 +130,15 @@ std::string SaveFileBaseCommand::saveAsDialog(
// preferences. // preferences.
Preferences::instance().save(); Preferences::instance().save();
std::string filename; std::string filename = params().filename();
if (filename.empty() || params().ui()) {
if (!m_filename.empty()) {
filename = m_filename;
}
else {
base::paths exts = get_writable_extensions(); base::paths exts = get_writable_extensions();
filename = initialFilename; filename = initialFilename;
#ifdef ENABLE_UI #ifdef ENABLE_UI
again:; again:;
base::paths newfilename; base::paths newfilename;
if (!m_useUI || if (!params().ui() ||
!app::show_file_selector( !app::show_file_selector(
dlgTitle, filename, exts, dlgTitle, filename, exts,
FileSelectorType::Save, FileSelectorType::Save,
@ -200,8 +185,8 @@ void SaveFileBaseCommand::saveDocumentInBackground(
const std::string& filename, const std::string& filename,
const MarkAsSaved markAsSaved) const MarkAsSaved markAsSaved)
{ {
if (!m_aniDir.empty()) { if (params().aniDir.isSet()) {
switch (convert_string_to_anidir(m_aniDir)) { switch (params().aniDir()) {
case AniDir::REVERSE: case AniDir::REVERSE:
m_selFrames = m_selFrames.makeReverse(); m_selFrames = m_selFrames.makeReverse();
break; break;
@ -211,7 +196,7 @@ void SaveFileBaseCommand::saveDocumentInBackground(
} }
} }
FileOpROI roi(document, m_slice, m_tag, FileOpROI roi(document, params().slice(), params().tag(),
m_selFrames, m_adjustFramesByTag); m_selFrames, m_adjustFramesByTag);
std::unique_ptr<FileOp> fop( std::unique_ptr<FileOp> fop(
@ -219,8 +204,8 @@ void SaveFileBaseCommand::saveDocumentInBackground(
context, context,
roi, roi,
filename, filename,
m_filenameFormat, params().filenameFormat(),
m_ignoreEmpty)); params().ignoreEmpty()));
if (!fop) if (!fop)
return; return;
@ -283,7 +268,8 @@ void SaveFileCommand::onExecute(Context* context)
saveDocumentInBackground( saveDocumentInBackground(
context, document, context, document,
documentReader->filename(), (params().filename.isSet() ? params().filename():
documentReader->filename()),
MarkAsSaved::On); MarkAsSaved::On);
} }
// If the document isn't associated to a file, we must to show the // If the document isn't associated to a file, we must to show the
@ -291,7 +277,8 @@ void SaveFileCommand::onExecute(Context* context)
// for this document. // for this document.
else { else {
saveAsDialog(context, "Save File", saveAsDialog(context, "Save File",
document->filename(), (params().filename.isSet() ? params().filename():
document->filename()),
MarkAsSaved::On); MarkAsSaved::On);
} }
} }
@ -313,7 +300,8 @@ void SaveFileAsCommand::onExecute(Context* context)
{ {
Doc* document = context->activeDocument(); Doc* document = context->activeDocument();
saveAsDialog(context, "Save As", saveAsDialog(context, "Save As",
document->filename(), (params().filename.isSet() ? params().filename():
document->filename()),
MarkAsSaved::On); MarkAsSaved::On);
} }
@ -337,17 +325,17 @@ SaveFileCopyAsCommand::SaveFileCopyAsCommand()
void SaveFileCopyAsCommand::onExecute(Context* context) void SaveFileCopyAsCommand::onExecute(Context* context)
{ {
Doc* doc = context->activeDocument(); Doc* doc = context->activeDocument();
std::string outputFilename = m_filename; std::string outputFilename = params().filename();
std::string layers = kAllLayers; std::string layers = kAllLayers;
std::string frames = kAllFrames; std::string frames = kAllFrames;
double xscale = 1.0; double xscale = 1.0;
double yscale = 1.0; double yscale = 1.0;
bool applyPixelRatio = false; bool applyPixelRatio = false;
doc::AniDir aniDirValue = convert_string_to_anidir(m_aniDir); doc::AniDir aniDirValue = params().aniDir();
bool isForTwitter = false; bool isForTwitter = false;
#if ENABLE_UI #if ENABLE_UI
if (m_useUI && context->isUIAvailable()) { if (params().ui() && context->isUIAvailable()) {
ExportFileWindow win(doc); ExportFileWindow win(doc);
bool askOverwrite = true; bool askOverwrite = true;
@ -367,6 +355,8 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
return result; return result;
}); });
win.setAniDir(aniDirValue);
win.remapWindow(); win.remapWindow();
load_window_pos(&win, "ExportFile"); load_window_pos(&win, "ExportFile");
again:; again:;
@ -446,20 +436,22 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
layers, layers,
layersVisibility); layersVisibility);
// Selected frames to export // m_selFrames is not empty if fromFrame/toFrame parameters are
SelectedFrames selFrames; // specified.
Tag* tag = calculate_selected_frames( if (m_selFrames.empty()) {
site, frames, selFrames); // Selected frames to export
if (tag) SelectedFrames selFrames;
m_tag = tag->name(); Tag* tag = calculate_selected_frames(
m_selFrames = selFrames; site, frames, selFrames);
if (tag)
params().tag(tag->name());
m_selFrames = selFrames;
}
m_adjustFramesByTag = false; m_adjustFramesByTag = false;
} }
base::ScopedValue<std::string> restoreAniDir( // Set ani dir
m_aniDir, params().aniDir(aniDirValue);
convert_anidir_to_string(aniDirValue), // New value
m_aniDir); // Restore old value
// TODO This should be set as options for the specific encoder // TODO This should be set as options for the specific encoder
GifEncoderDurationFix fixGif(isForTwitter); GifEncoderDurationFix fixGif(isForTwitter);

View File

@ -10,6 +10,8 @@
#pragma once #pragma once
#include "app/commands/command.h" #include "app/commands/command.h"
#include "app/commands/new_params.h"
#include "doc/anidir.h"
#include "doc/selected_frames.h" #include "doc/selected_frames.h"
#include <string> #include <string>
@ -17,7 +19,19 @@
namespace app { namespace app {
class Doc; class Doc;
class SaveFileBaseCommand : public Command { struct SaveFileParams : public NewParams {
Param<bool> ui { this, true, { "ui", "useUI" } };
Param<std::string> filename { this, std::string(), "filename" };
Param<std::string> filenameFormat { this, std::string(), { "filenameFormat", "filename-format" } };
Param<std::string> tag { this, std::string(), { "tag", "frame-tag" } };
Param<doc::AniDir> aniDir { this, doc::AniDir::FORWARD, { "aniDir", "ani-dir" } };
Param<std::string> slice { this, std::string(), "slice" };
Param<doc::frame_t> fromFrame { this, 0, { "fromFrame", "from-frame" } };
Param<doc::frame_t> toFrame { this, 0, { "toFrame", "to-frame" } };
Param<bool> ignoreEmpty { this, false, "ignoreEmpty" };
};
class SaveFileBaseCommand : public CommandWithNewParams<SaveFileParams> {
public: public:
enum class MarkAsSaved { Off, On }; enum class MarkAsSaved { Off, On };
enum class SaveInBackground { Off, On }; enum class SaveInBackground { Off, On };
@ -41,15 +55,8 @@ namespace app {
const std::string& filename, const std::string& filename,
const MarkAsSaved markAsSaved); const MarkAsSaved markAsSaved);
std::string m_filename;
std::string m_filenameFormat;
std::string m_tag;
std::string m_aniDir;
std::string m_slice;
doc::SelectedFrames m_selFrames; doc::SelectedFrames m_selFrames;
bool m_adjustFramesByTag; bool m_adjustFramesByTag;
bool m_useUI;
bool m_ignoreEmpty;
}; };
} // namespace app } // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019-2021 Igara Studio S.A. // Copyright (C) 2019-2022 Igara Studio S.A.
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -18,6 +18,7 @@
#include "base/split_string.h" #include "base/split_string.h"
#include "base/string.h" #include "base/string.h"
#include "doc/algorithm/resize_image.h" #include "doc/algorithm/resize_image.h"
#include "doc/anidir.h"
#include "doc/color_mode.h" #include "doc/color_mode.h"
#include "filters/color_curve.h" #include "filters/color_curve.h"
#include "filters/hue_saturation_filter.h" #include "filters/hue_saturation_filter.h"
@ -144,6 +145,12 @@ void Param<doc::ColorMode>::fromString(const std::string& value)
setValue(doc::ColorMode::RGB); setValue(doc::ColorMode::RGB);
} }
template<>
void Param<doc::AniDir>::fromString(const std::string& value)
{
setValue(convert_string_to_anidir(value));
}
template<> template<>
void Param<app::Color>::fromString(const std::string& value) void Param<app::Color>::fromString(const std::string& value)
{ {
@ -303,6 +310,15 @@ void Param<doc::ColorMode>::fromLua(lua_State* L, int index)
setValue((doc::ColorMode)lua_tointeger(L, index)); setValue((doc::ColorMode)lua_tointeger(L, index));
} }
template<>
void Param<doc::AniDir>::fromLua(lua_State* L, int index)
{
if (lua_type(L, index) == LUA_TSTRING)
fromString(lua_tostring(L, index));
else
setValue((doc::AniDir)lua_tointeger(L, index));
}
template<> template<>
void Param<app::Color>::fromLua(lua_State* L, int index) void Param<app::Color>::fromLua(lua_State* L, int index)
{ {

View File

@ -10,6 +10,6 @@
// Increment this value if the scripting API is modified between two // Increment this value if the scripting API is modified between two
// released Aseprite versions. // released Aseprite versions.
#define API_VERSION 18 #define API_VERSION 19
#endif #endif

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2018 David Capello // Copyright (C) 2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -141,6 +141,11 @@ bool ExportFileWindow::isForTwitter() const
return forTwitter()->isSelected(); return forTwitter()->isSelected();
} }
void ExportFileWindow::setAniDir(const doc::AniDir aniDir)
{
anidir()->setSelectedItemIndex(int(aniDir));
}
void ExportFileWindow::setOutputFilename(const std::string& pathAndFilename) void ExportFileWindow::setOutputFilename(const std::string& pathAndFilename)
{ {
m_outputPath = base::get_file_path(pathAndFilename); m_outputPath = base::get_file_path(pathAndFilename);

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2020-2022 Igara Studio S.A.
// Copyright (C) 2018 David Capello // Copyright (C) 2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -34,6 +34,8 @@ namespace app {
bool applyPixelRatio() const; bool applyPixelRatio() const;
bool isForTwitter() const; bool isForTwitter() const;
void setAniDir(const doc::AniDir aniDir);
obs::signal<std::string()> SelectOutputFile; obs::signal<std::string()> SelectOutputFile;
private: private: