From f24eb75298c118500ff4428661fe186eefdde2b2 Mon Sep 17 00:00:00 2001 From: David N Campo Date: Fri, 22 Mar 2019 10:54:20 -0300 Subject: [PATCH] Add --trim-by-grid CLI option --- data/gui.xml | 4 ++++ src/app/cli/app_options.cpp | 1 + src/app/cli/app_options.h | 2 ++ src/app/cli/cli_open_file.cpp | 1 + src/app/cli/cli_open_file.h | 1 + src/app/cli/cli_processor.cpp | 18 ++++++++++++++++-- src/app/cli/preview_cli_delegate.cpp | 5 ++++- src/app/commands/cmd_crop.cpp | 28 ++++++++++++++++++++++++++-- src/app/doc_api.cpp | 18 +++++++++++++++++- src/app/doc_api.h | 2 +- 10 files changed, 73 insertions(+), 7 deletions(-) diff --git a/data/gui.xml b/data/gui.xml index a3b41dffe..71db68991 100644 --- a/data/gui.xml +++ b/data/gui.xml @@ -480,6 +480,10 @@ + + + + diff --git a/src/app/cli/app_options.cpp b/src/app/cli/app_options.cpp index e0bd1005e..bfe6f1361 100644 --- a/src/app/cli/app_options.cpp +++ b/src/app/cli/app_options.cpp @@ -59,6 +59,7 @@ AppOptions::AppOptions(int argc, const char* argv[]) , m_shapePadding(m_po.add("shape-padding").requiresValue("").description("Add padding between frames")) , m_innerPadding(m_po.add("inner-padding").requiresValue("").description("Add padding inside each frame")) , m_trim(m_po.add("trim").description("Trim all images before exporting")) + , m_trimByGrid(m_po.add("trim-by-grid").description("Trim all images by its correspondent grid boundaries before exporting")) , m_crop(m_po.add("crop").requiresValue("x,y,width,height").description("Crop all the images to the given rectangle")) , m_slice(m_po.add("slice").requiresValue("").description("Crop the sprite to the given slice area")) , m_filenameFormat(m_po.add("filename-format").requiresValue("").description("Special format to generate filenames")) diff --git a/src/app/cli/app_options.h b/src/app/cli/app_options.h index ecace8aab..101bb1711 100644 --- a/src/app/cli/app_options.h +++ b/src/app/cli/app_options.h @@ -73,6 +73,7 @@ public: const Option& shapePadding() const { return m_shapePadding; } const Option& innerPadding() const { return m_innerPadding; } const Option& trim() const { return m_trim; } + const Option& trimByGrid() const { return m_trimByGrid; } const Option& crop() const { return m_crop; } const Option& slice() const { return m_slice; } const Option& filenameFormat() const { return m_filenameFormat; } @@ -132,6 +133,7 @@ private: Option& m_shapePadding; Option& m_innerPadding; Option& m_trim; + Option& m_trimByGrid; Option& m_crop; Option& m_slice; Option& m_filenameFormat; diff --git a/src/app/cli/cli_open_file.cpp b/src/app/cli/cli_open_file.cpp index d67bd72e6..a302d647c 100644 --- a/src/app/cli/cli_open_file.cpp +++ b/src/app/cli/cli_open_file.cpp @@ -32,6 +32,7 @@ CliOpenFile::CliOpenFile() listSlices = false; ignoreEmpty = false; trim = false; + trimByGrid = false; oneFrame = false; crop = gfx::Rect(); } diff --git a/src/app/cli/cli_open_file.h b/src/app/cli/cli_open_file.h index caf29be77..2ad6cf61b 100644 --- a/src/app/cli/cli_open_file.h +++ b/src/app/cli/cli_open_file.h @@ -37,6 +37,7 @@ namespace app { bool listSlices; bool ignoreEmpty; bool trim; + bool trimByGrid; bool oneFrame; gfx::Rect crop; diff --git a/src/app/cli/cli_processor.cpp b/src/app/cli/cli_processor.cpp index 30fb127a1..094af4bbc 100644 --- a/src/app/cli/cli_processor.cpp +++ b/src/app/cli/cli_processor.cpp @@ -271,6 +271,14 @@ void CliProcessor::process(Context* ctx) if (m_exporter) m_exporter->setTrimCels(true); } + // --trim-by-grid + else if (opt == &m_options.trimByGrid()) { + cof.trim = cof.trimByGrid = true; + if (m_exporter) { + m_exporter->setTrimCels(true); + m_exporter->setTrimByGrid(true); + } + } // --crop x,y,width,height else if (opt == &m_options.crop()) { std::vector parts; @@ -712,8 +720,13 @@ void CliProcessor::saveFile(Context* ctx, const CliOpenFile& cof) // don't have sheet .json) Also, we should trim each frame // individually (a process that can be done only in // FileOp::operate()). - if (cof.trim) - ctx->executeCommand(trimCommand); + if (cof.trim) { + Params params; + if (cof.trimByGrid) { + params.set("byGrid", "true"); + } + ctx->executeCommand(trimCommand, params); + } CliOpenFile itemCof = cof; FilenameInfo fnInfo; @@ -744,6 +757,7 @@ void CliProcessor::saveFile(Context* ctx, const CliOpenFile& cof) // Call delegate m_delegate->saveFile(ctx, itemCof); + // for trim or trimByGrid case if (cof.trim) { ctx->executeCommand(undoCommand); clearUndo = true; diff --git a/src/app/cli/preview_cli_delegate.cpp b/src/app/cli/preview_cli_delegate.cpp index fe5a500b7..9c3d27708 100644 --- a/src/app/cli/preview_cli_delegate.cpp +++ b/src/app/cli/preview_cli_delegate.cpp @@ -96,7 +96,10 @@ void PreviewCliDelegate::saveFile(Context* ctx, const CliOpenFile& cof) } if (cof.trim) { - std::cout << " - Trim\n"; + if (cof.trimByGrid) + std::cout << " - Trim by Grid\n"; + else + std::cout << " - Trim\n"; } if (cof.ignoreEmpty) { diff --git a/src/app/commands/cmd_crop.cpp b/src/app/commands/cmd_crop.cpp index c3255b1a5..76821dba3 100644 --- a/src/app/commands/cmd_crop.cpp +++ b/src/app/commands/cmd_crop.cpp @@ -12,6 +12,7 @@ #include "app/commands/command.h" #include "app/context_access.h" #include "app/doc_api.h" +#include "app/i18n/strings.h" #include "app/modules/gui.h" #include "app/tx.h" #include "app/ui/color_bar.h" @@ -87,8 +88,13 @@ public: AutocropSpriteCommand(); protected: + void onLoadParams(const Params& params) override; bool onEnabled(Context* context) override; void onExecute(Context* context) override; + std::string onGetFriendlyName() const override; + +private: + bool m_byGrid = false; }; AutocropSpriteCommand::AutocropSpriteCommand() @@ -96,6 +102,16 @@ AutocropSpriteCommand::AutocropSpriteCommand() { } +void AutocropSpriteCommand::onLoadParams(const app::Params ¶ms) +{ + m_byGrid = false; + if (params.has_param("byGrid")) { + std::string isByGrid = params.get("byGrid"); + if (isByGrid == "true") + m_byGrid = true; + } +} + bool AutocropSpriteCommand::onEnabled(Context* context) { return context->checkFlags(ContextFlags::ActiveDocumentIsWritable | @@ -108,8 +124,8 @@ void AutocropSpriteCommand::onExecute(Context* context) Doc* document(writer.document()); Sprite* sprite(writer.sprite()); { - Tx tx(writer.context(), "Trim Sprite"); - document->getApi(tx).trimSprite(sprite); + Tx tx(writer.context(), onGetFriendlyName()); + document->getApi(tx).trimSprite(sprite, m_byGrid); tx.commit(); } @@ -119,6 +135,14 @@ void AutocropSpriteCommand::onExecute(Context* context) #endif } +std::string AutocropSpriteCommand::onGetFriendlyName() const +{ + if (m_byGrid) + return "Trim Sprite by Grid"; + else + return "Trim Sprite"; +} + Command* CommandFactory::createCropSpriteCommand() { return new CropSpriteCommand; diff --git a/src/app/doc_api.cpp b/src/app/doc_api.cpp index 189474a95..0a5a5b028 100644 --- a/src/app/doc_api.cpp +++ b/src/app/doc_api.cpp @@ -9,6 +9,7 @@ #endif #include "app/doc_api.h" +#include "app/snap_to_grid.h" #include "app/cmd/add_cel.h" #include "app/cmd/add_frame.h" @@ -45,6 +46,7 @@ #include "app/context.h" #include "app/doc.h" #include "app/doc_undo.h" +#include "app/pref/preferences.h" #include "app/transaction.h" #include "doc/algorithm/flip_image.h" #include "doc/algorithm/shrink_bounds.h" @@ -156,7 +158,7 @@ void DocApi::cropSprite(Sprite* sprite, const gfx::Rect& bounds) } } -void DocApi::trimSprite(Sprite* sprite) +void DocApi::trimSprite(Sprite* sprite, bool isByGrid) { gfx::Rect bounds; @@ -174,6 +176,20 @@ void DocApi::trimSprite(Sprite* sprite) gfx::Rect frameBounds; if (doc::algorithm::shrink_bounds(image, frameBounds, get_pixel(image, 0, 0))) bounds = bounds.createUnion(frameBounds); + + if (isByGrid) { + Doc* doc = m_document; + auto& docPref = Preferences::instance().document(doc); + gfx::Point posTopLeft = + snap_to_grid(docPref.grid.bounds(), + bounds.origin(), + PreferSnapTo::FloorGrid); + gfx::Point posBottomRight = + snap_to_grid(docPref.grid.bounds(), + bounds.point2(), + PreferSnapTo::CeilGrid); + bounds = gfx::Rect(posTopLeft, posBottomRight); + } } if (!bounds.isEmpty()) diff --git a/src/app/doc_api.h b/src/app/doc_api.h index 977242a73..b6ba57ee5 100644 --- a/src/app/doc_api.h +++ b/src/app/doc_api.h @@ -45,7 +45,7 @@ namespace app { void setSpriteSize(Sprite* sprite, int w, int h); void setSpriteTransparentColor(Sprite* sprite, color_t maskColor); void cropSprite(Sprite* sprite, const gfx::Rect& bounds); - void trimSprite(Sprite* sprite); + void trimSprite(Sprite* sprite, bool isByGrid); // Frames API void addFrame(Sprite* sprite, frame_t newFrame);