From ddc1b762144330f15ffbe0ce8388365fc9a1e476 Mon Sep 17 00:00:00 2001 From: David Capello Date: Mon, 13 Jun 2022 17:04:12 -0300 Subject: [PATCH] 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 --- src/app/commands/cmd_save_file.cpp | 84 ++++++++++++++---------------- src/app/commands/cmd_save_file.h | 23 +++++--- src/app/commands/new_params.cpp | 18 ++++++- src/app/script/api_version.h | 2 +- src/app/ui/export_file_window.cpp | 7 ++- src/app/ui/export_file_window.h | 4 +- 6 files changed, 80 insertions(+), 58 deletions(-) diff --git a/src/app/commands/cmd_save_file.cpp b/src/app/commands/cmd_save_file.cpp index 335e80f35..f4f579d48 100644 --- a/src/app/commands/cmd_save_file.cpp +++ b/src/app/commands/cmd_save_file.cpp @@ -86,24 +86,18 @@ private: ////////////////////////////////////////////////////////////////////// SaveFileBaseCommand::SaveFileBaseCommand(const char* id, CommandFlags flags) - : Command(id, flags) + : CommandWithNewParams(id, flags) { - m_useUI = true; - m_ignoreEmpty = false; } void SaveFileBaseCommand::onLoadParams(const Params& params) { - m_filename = params.get("filename"); - m_filenameFormat = params.get("filename-format"); - m_tag = params.get("frame-tag"); - m_aniDir = params.get("ani-dir"); - m_slice = params.get("slice"); + CommandWithNewParams::onLoadParams(params); - if (params.has_param("from-frame") || - params.has_param("to-frame")) { - doc::frame_t fromFrame = params.get_as("from-frame"); - doc::frame_t toFrame = params.get_as("to-frame"); + if (this->params().fromFrame.isSet() || + this->params().toFrame.isSet()) { + doc::frame_t fromFrame = this->params().fromFrame(); + doc::frame_t toFrame = this->params().toFrame(); m_selFrames.insert(fromFrame, toFrame); m_adjustFramesByTag = true; } @@ -111,11 +105,6 @@ void SaveFileBaseCommand::onLoadParams(const Params& params) m_selFrames.clear(); m_adjustFramesByTag = false; } - - std::string useUI = params.get("useUI"); - m_useUI = (useUI.empty() || (useUI == "true")); - - m_ignoreEmpty = params.get_as("ignoreEmpty"); } // Returns true if there is a current sprite to save. @@ -141,19 +130,15 @@ std::string SaveFileBaseCommand::saveAsDialog( // preferences. Preferences::instance().save(); - std::string filename; - - if (!m_filename.empty()) { - filename = m_filename; - } - else { + std::string filename = params().filename(); + if (filename.empty() || params().ui()) { base::paths exts = get_writable_extensions(); filename = initialFilename; #ifdef ENABLE_UI again:; base::paths newfilename; - if (!m_useUI || + if (!params().ui() || !app::show_file_selector( dlgTitle, filename, exts, FileSelectorType::Save, @@ -200,8 +185,8 @@ void SaveFileBaseCommand::saveDocumentInBackground( const std::string& filename, const MarkAsSaved markAsSaved) { - if (!m_aniDir.empty()) { - switch (convert_string_to_anidir(m_aniDir)) { + if (params().aniDir.isSet()) { + switch (params().aniDir()) { case AniDir::REVERSE: m_selFrames = m_selFrames.makeReverse(); 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); std::unique_ptr fop( @@ -219,8 +204,8 @@ void SaveFileBaseCommand::saveDocumentInBackground( context, roi, filename, - m_filenameFormat, - m_ignoreEmpty)); + params().filenameFormat(), + params().ignoreEmpty())); if (!fop) return; @@ -283,7 +268,8 @@ void SaveFileCommand::onExecute(Context* context) saveDocumentInBackground( context, document, - documentReader->filename(), + (params().filename.isSet() ? params().filename(): + documentReader->filename()), MarkAsSaved::On); } // 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. else { saveAsDialog(context, "Save File", - document->filename(), + (params().filename.isSet() ? params().filename(): + document->filename()), MarkAsSaved::On); } } @@ -313,7 +300,8 @@ void SaveFileAsCommand::onExecute(Context* context) { Doc* document = context->activeDocument(); saveAsDialog(context, "Save As", - document->filename(), + (params().filename.isSet() ? params().filename(): + document->filename()), MarkAsSaved::On); } @@ -337,17 +325,17 @@ SaveFileCopyAsCommand::SaveFileCopyAsCommand() void SaveFileCopyAsCommand::onExecute(Context* context) { Doc* doc = context->activeDocument(); - std::string outputFilename = m_filename; + std::string outputFilename = params().filename(); std::string layers = kAllLayers; std::string frames = kAllFrames; double xscale = 1.0; double yscale = 1.0; bool applyPixelRatio = false; - doc::AniDir aniDirValue = convert_string_to_anidir(m_aniDir); + doc::AniDir aniDirValue = params().aniDir(); bool isForTwitter = false; #if ENABLE_UI - if (m_useUI && context->isUIAvailable()) { + if (params().ui() && context->isUIAvailable()) { ExportFileWindow win(doc); bool askOverwrite = true; @@ -367,6 +355,8 @@ void SaveFileCopyAsCommand::onExecute(Context* context) return result; }); + win.setAniDir(aniDirValue); + win.remapWindow(); load_window_pos(&win, "ExportFile"); again:; @@ -446,20 +436,22 @@ void SaveFileCopyAsCommand::onExecute(Context* context) layers, layersVisibility); - // Selected frames to export - SelectedFrames selFrames; - Tag* tag = calculate_selected_frames( - site, frames, selFrames); - if (tag) - m_tag = tag->name(); - m_selFrames = selFrames; + // m_selFrames is not empty if fromFrame/toFrame parameters are + // specified. + if (m_selFrames.empty()) { + // Selected frames to export + SelectedFrames selFrames; + Tag* tag = calculate_selected_frames( + site, frames, selFrames); + if (tag) + params().tag(tag->name()); + m_selFrames = selFrames; + } m_adjustFramesByTag = false; } - base::ScopedValue restoreAniDir( - m_aniDir, - convert_anidir_to_string(aniDirValue), // New value - m_aniDir); // Restore old value + // Set ani dir + params().aniDir(aniDirValue); // TODO This should be set as options for the specific encoder GifEncoderDurationFix fixGif(isForTwitter); diff --git a/src/app/commands/cmd_save_file.h b/src/app/commands/cmd_save_file.h index 635900a5f..f165a1046 100644 --- a/src/app/commands/cmd_save_file.h +++ b/src/app/commands/cmd_save_file.h @@ -10,6 +10,8 @@ #pragma once #include "app/commands/command.h" +#include "app/commands/new_params.h" +#include "doc/anidir.h" #include "doc/selected_frames.h" #include @@ -17,7 +19,19 @@ namespace app { class Doc; - class SaveFileBaseCommand : public Command { + struct SaveFileParams : public NewParams { + Param ui { this, true, { "ui", "useUI" } }; + Param filename { this, std::string(), "filename" }; + Param filenameFormat { this, std::string(), { "filenameFormat", "filename-format" } }; + Param tag { this, std::string(), { "tag", "frame-tag" } }; + Param aniDir { this, doc::AniDir::FORWARD, { "aniDir", "ani-dir" } }; + Param slice { this, std::string(), "slice" }; + Param fromFrame { this, 0, { "fromFrame", "from-frame" } }; + Param toFrame { this, 0, { "toFrame", "to-frame" } }; + Param ignoreEmpty { this, false, "ignoreEmpty" }; + }; + + class SaveFileBaseCommand : public CommandWithNewParams { public: enum class MarkAsSaved { Off, On }; enum class SaveInBackground { Off, On }; @@ -41,15 +55,8 @@ namespace app { const std::string& filename, 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; bool m_adjustFramesByTag; - bool m_useUI; - bool m_ignoreEmpty; }; } // namespace app diff --git a/src/app/commands/new_params.cpp b/src/app/commands/new_params.cpp index 0dd0f6309..f3f10ea75 100644 --- a/src/app/commands/new_params.cpp +++ b/src/app/commands/new_params.cpp @@ -1,5 +1,5 @@ // 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 // the End-User License Agreement for Aseprite. @@ -18,6 +18,7 @@ #include "base/split_string.h" #include "base/string.h" #include "doc/algorithm/resize_image.h" +#include "doc/anidir.h" #include "doc/color_mode.h" #include "filters/color_curve.h" #include "filters/hue_saturation_filter.h" @@ -144,6 +145,12 @@ void Param::fromString(const std::string& value) setValue(doc::ColorMode::RGB); } +template<> +void Param::fromString(const std::string& value) +{ + setValue(convert_string_to_anidir(value)); +} + template<> void Param::fromString(const std::string& value) { @@ -303,6 +310,15 @@ void Param::fromLua(lua_State* L, int index) setValue((doc::ColorMode)lua_tointeger(L, index)); } +template<> +void Param::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<> void Param::fromLua(lua_State* L, int index) { diff --git a/src/app/script/api_version.h b/src/app/script/api_version.h index 4f66ee469..c5269d02f 100644 --- a/src/app/script/api_version.h +++ b/src/app/script/api_version.h @@ -10,6 +10,6 @@ // Increment this value if the scripting API is modified between two // released Aseprite versions. -#define API_VERSION 18 +#define API_VERSION 19 #endif diff --git a/src/app/ui/export_file_window.cpp b/src/app/ui/export_file_window.cpp index 476279d7e..f84de4983 100644 --- a/src/app/ui/export_file_window.cpp +++ b/src/app/ui/export_file_window.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019-2020 Igara Studio S.A. +// Copyright (C) 2019-2022 Igara Studio S.A. // Copyright (C) 2018 David Capello // // This program is distributed under the terms of @@ -141,6 +141,11 @@ bool ExportFileWindow::isForTwitter() const return forTwitter()->isSelected(); } +void ExportFileWindow::setAniDir(const doc::AniDir aniDir) +{ + anidir()->setSelectedItemIndex(int(aniDir)); +} + void ExportFileWindow::setOutputFilename(const std::string& pathAndFilename) { m_outputPath = base::get_file_path(pathAndFilename); diff --git a/src/app/ui/export_file_window.h b/src/app/ui/export_file_window.h index 9aa1338a2..80b8c29a1 100644 --- a/src/app/ui/export_file_window.h +++ b/src/app/ui/export_file_window.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2020 Igara Studio S.A. +// Copyright (C) 2020-2022 Igara Studio S.A. // Copyright (C) 2018 David Capello // // This program is distributed under the terms of @@ -34,6 +34,8 @@ namespace app { bool applyPixelRatio() const; bool isForTwitter() const; + void setAniDir(const doc::AniDir aniDir); + obs::signal SelectOutputFile; private: