diff --git a/src/app/cli/cli_processor.cpp b/src/app/cli/cli_processor.cpp index fc48a0fe9..f7d5e8066 100644 --- a/src/app/cli/cli_processor.cpp +++ b/src/app/cli/cli_processor.cpp @@ -202,8 +202,9 @@ void CliProcessor::process() // Automatic --split-layer or --split-tags in case the // output filename already contains {layer} or {tag} // template elements. - bool hasLayerTemplate = (fn.find("{layer}") != std::string::npos); - bool hasTagTemplate = (fn.find("{tag}") != std::string::npos); + bool hasLayerTemplate = (is_layer_in_filename_format(fn) || + is_group_in_filename_format(fn)); + bool hasTagTemplate = is_tag_in_filename_format(fn); if (hasLayerTemplate || hasTagTemplate) { cof.splitLayers = (cof.splitLayers || hasLayerTemplate); cof.splitTags = (cof.splitTags || hasTagTemplate); @@ -481,6 +482,9 @@ void CliProcessor::saveFile(const CliOpenFile& cof) frameTags.push_back(nullptr); } + bool layerInFormat = is_layer_in_filename_format(fn); + bool groupInFormat = is_group_in_filename_format(fn); + for (doc::FrameTag* frameTag : frameTags) { // For each layer, hide other ones and save the sprite. i = 0; @@ -497,6 +501,13 @@ void CliProcessor::saveFile(const CliOpenFile& cof) hide->setVisible(hide == layer); } + if (layer) { + if ((layerInFormat && layer->isGroup()) || + (!layerInFormat && groupInFormat && !layer->isGroup())) { + continue; + } + } + // TODO --trim --save-as --split-layers doesn't make too much // sense as we lost the trim rectangle information (e.g. we // don't have sheet .json) Also, we should trim each frame @@ -510,6 +521,12 @@ void CliProcessor::saveFile(const CliOpenFile& cof) fnInfo.filename(fn); if (layer) { fnInfo.layerName(layer->name()); + + if (layer->isGroup()) + fnInfo.groupName(layer->name()); + else if (layer->parent() != layer->sprite()->root()) + fnInfo.groupName(layer->parent()->name()); + itemCof.importLayer = layer->name(); } if (frameTag) { diff --git a/src/app/document_exporter.cpp b/src/app/document_exporter.cpp index 8f167d7bc..b013d2214 100644 --- a/src/app/document_exporter.cpp +++ b/src/app/document_exporter.cpp @@ -487,6 +487,7 @@ void DocumentExporter::captureSamples(Samples& samples) fnInfo .filename(doc->filename()) .layerName(layer ? layer->name(): "") + .groupName(layer && layer->parent() != sprite->root() ? layer->parent()->name(): "") .innerTagName(innerTag ? innerTag->name(): "") .outerTagName(outerTag ? outerTag->name(): "") .frame((frames > 1) ? frame-frameFirst: frame_t(-1)); diff --git a/src/app/filename_formatter.cpp b/src/app/filename_formatter.cpp index 79e9dd35f..6ff4b026d 100644 --- a/src/app/filename_formatter.cpp +++ b/src/app/filename_formatter.cpp @@ -73,6 +73,21 @@ bool get_frame_info_from_filename_format( return false; } +bool is_tag_in_filename_format(const std::string& format) +{ + return (format.find("{tag}") != std::string::npos); +} + +bool is_layer_in_filename_format(const std::string& format) +{ + return (format.find("{layer}") != std::string::npos); +} + +bool is_group_in_filename_format(const std::string& format) +{ + return (format.find("{group}") != std::string::npos); +} + std::string filename_formatter( const std::string& format, FilenameInfo& info, @@ -90,6 +105,7 @@ std::string filename_formatter( base::replace_string(output, "{title}", base::get_file_title(filename)); base::replace_string(output, "{extension}", base::get_file_extension(filename)); base::replace_string(output, "{layer}", info.layerName()); + base::replace_string(output, "{group}", info.groupName()); if (replaceFrame) { base::replace_string(output, "{tag}", info.innerTagName()); diff --git a/src/app/filename_formatter.h b/src/app/filename_formatter.h index a828dad50..28ee2660c 100644 --- a/src/app/filename_formatter.h +++ b/src/app/filename_formatter.h @@ -18,6 +18,7 @@ namespace app { const std::string& filename() const { return m_filename; } const std::string& layerName() const { return m_layerName; } + const std::string& groupName() const { return m_groupName; } const std::string& innerTagName() const { return m_innerTagName; } const std::string& outerTagName() const { return m_outerTagName; } int frame() const { return m_frame; } @@ -33,6 +34,11 @@ namespace app { return *this; } + FilenameInfo& groupName(const std::string& value) { + m_groupName = value; + return *this; + } + FilenameInfo& innerTagName(const std::string& value) { m_innerTagName = value; return *this; @@ -56,6 +62,7 @@ namespace app { private: std::string m_filename; std::string m_layerName; + std::string m_groupName; std::string m_innerTagName; std::string m_outerTagName; int m_frame; @@ -67,6 +74,11 @@ namespace app { bool get_frame_info_from_filename_format( const std::string& format, int* startFrom, int* width); + // Returns true if the given filename format contains {tag}, {layer} or {group} + bool is_tag_in_filename_format(const std::string& format); + bool is_layer_in_filename_format(const std::string& format); + bool is_group_in_filename_format(const std::string& format); + // If "replaceFrame" is false, this function doesn't replace all the // information that depends on the current frame ({frame}, // {tagframe}, {tag}, etc.) diff --git a/src/app/filename_formatter_tests.cpp b/src/app/filename_formatter_tests.cpp index a4a503b04..5d7da2925 100644 --- a/src/app/filename_formatter_tests.cpp +++ b/src/app/filename_formatter_tests.cpp @@ -150,6 +150,22 @@ TEST(FilenameFormatter, WithTagFrame) FilenameInfo().filename("./file.png").frame(2).tagFrame(1))); } +TEST(FilenameFormatter, WithGroup) +{ + EXPECT_EQ( + "C:/temp/file (-Eyes).png", + filename_formatter( + "{path}/{title} ({group}-{layer}).{extension}", + FilenameInfo().filename("C:/temp/file.png") + .layerName("Eyes"))); + EXPECT_EQ( + "C:/temp/file (Face-Eyes).png", + filename_formatter( + "{path}/{title} ({group}-{layer}).{extension}", + FilenameInfo().filename("C:/temp/file.png") + .groupName("Face").layerName("Eyes"))); +} + TEST(FilenameFormatter, GetFrameInfo) { int frameBase, width;