From 88ef46de42e35f234b4a79a7c81c833b1db30c7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Capello?= Date: Mon, 13 May 2024 17:59:36 -0300 Subject: [PATCH] Add new CLI param to save animations taking into account subtabs and repeats (fix #4297) --- src/app/cli/app_options.cpp | 1 + src/app/cli/app_options.h | 2 ++ src/app/cli/cli_open_file.h | 1 + src/app/cli/cli_processor.cpp | 4 ++++ src/app/cli/default_cli_delegate.cpp | 3 +++ src/app/cli/preview_cli_delegate.cpp | 4 ++++ src/app/commands/cmd_save_file.cpp | 29 ++++++++++++++-------------- 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/app/cli/app_options.cpp b/src/app/cli/app_options.cpp index 741863173..6e1a1981f 100644 --- a/src/app/cli/app_options.cpp +++ b/src/app/cli/app_options.cpp @@ -54,6 +54,7 @@ AppOptions::AppOptions(int argc, const char* argv[]) , m_allLayers(m_po.add("all-layers").description("Make all layers visible\nBy default hidden layers will be ignored")) , m_ignoreLayer(m_po.add("ignore-layer").requiresValue("").description("Exclude the given layer in the sheet\nor save as operation")) , m_tag(m_po.add("tag").alias("frame-tag").requiresValue("").description("Include tagged frames in the sheet")) + , m_playSubtags(m_po.add("play-subtags").description("Play subtags and repeats when saving the frames of an animated sprite")) , m_frameRange(m_po.add("frame-range").requiresValue("from,to").description("Only export frames in the [from,to] range")) , m_ignoreEmpty(m_po.add("ignore-empty").description("Do not export empty frames/cels")) , m_mergeDuplicates(m_po.add("merge-duplicates").description("Merge all duplicate frames into one in the sprite sheet")) diff --git a/src/app/cli/app_options.h b/src/app/cli/app_options.h index 5d3cbde43..eee082639 100644 --- a/src/app/cli/app_options.h +++ b/src/app/cli/app_options.h @@ -70,6 +70,7 @@ public: const Option& allLayers() const { return m_allLayers; } const Option& ignoreLayer() const { return m_ignoreLayer; } const Option& tag() const { return m_tag; } + const Option& playSubtags() const { return m_playSubtags; } const Option& frameRange() const { return m_frameRange; } const Option& ignoreEmpty() const { return m_ignoreEmpty; } const Option& mergeDuplicates() const { return m_mergeDuplicates; } @@ -143,6 +144,7 @@ private: Option& m_allLayers; Option& m_ignoreLayer; Option& m_tag; + Option& m_playSubtags; Option& m_frameRange; Option& m_ignoreEmpty; Option& m_mergeDuplicates; diff --git a/src/app/cli/cli_open_file.h b/src/app/cli/cli_open_file.h index 5e51f066b..003bcb030 100644 --- a/src/app/cli/cli_open_file.h +++ b/src/app/cli/cli_open_file.h @@ -44,6 +44,7 @@ namespace app { bool trimByGrid = false; bool oneFrame = false; bool exportTileset = false; + bool playSubtags = false; gfx::Rect crop; bool hasTag() const { diff --git a/src/app/cli/cli_processor.cpp b/src/app/cli/cli_processor.cpp index d09a07845..498efc2c1 100644 --- a/src/app/cli/cli_processor.cpp +++ b/src/app/cli/cli_processor.cpp @@ -303,6 +303,10 @@ int CliProcessor::process(Context* ctx) else if (opt == &m_options.tag()) { cof.tag = value.value(); } + // --play-subtags + else if (opt == &m_options.playSubtags()) { + cof.playSubtags = true; + } // --frame-range from,to else if (opt == &m_options.frameRange()) { std::vector splitRange; diff --git a/src/app/cli/default_cli_delegate.cpp b/src/app/cli/default_cli_delegate.cpp index 4f0e78241..0ab323827 100644 --- a/src/app/cli/default_cli_delegate.cpp +++ b/src/app/cli/default_cli_delegate.cpp @@ -88,6 +88,9 @@ void DefaultCliDelegate::saveFile(Context* ctx, const CliOpenFile& cof) if (cof.hasTag()) { params.set("frame-tag", cof.tag.c_str()); } + if (cof.playSubtags) { + params.set("playSubtags", "true"); + } if (cof.hasFrameRange()) { params.set("from-frame", base::convert_to(cof.fromFrame).c_str()); params.set("to-frame", base::convert_to(cof.toFrame).c_str()); diff --git a/src/app/cli/preview_cli_delegate.cpp b/src/app/cli/preview_cli_delegate.cpp index 82007e721..464675033 100644 --- a/src/app/cli/preview_cli_delegate.cpp +++ b/src/app/cli/preview_cli_delegate.cpp @@ -121,6 +121,10 @@ void PreviewCliDelegate::saveFile(Context* ctx, const CliOpenFile& cof) std::cout << " - Tag: '" << cof.tag << "'\n"; } + if (cof.playSubtags) { + std::cout << " - Play subtags & repeats\n"; + } + if (cof.hasSlice()) { std::cout << " - Slice: '" << cof.slice << "'\n"; } diff --git a/src/app/commands/cmd_save_file.cpp b/src/app/commands/cmd_save_file.cpp index c5c6923a0..4f00aba55 100644 --- a/src/app/commands/cmd_save_file.cpp +++ b/src/app/commands/cmd_save_file.cpp @@ -494,29 +494,28 @@ void SaveFileCopyAsCommand::onExecute(Context* context) { RestoreVisibleLayers layersVisibility; + Site site = context->activeSite(); if (context->isUIAvailable()) { - Site site = context->activeSite(); - // Selected layers to export calculate_visible_layers(site, layers, layersIndex, layersVisibility); - - // m_selFrames is not empty if fromFrame/toFrame parameters are - // specified. - if (m_framesSeq.empty()) { - // Frames sequence to export - FramesSequence framesSeq; - Tag* tag = calculate_frames_sequence( - site, frames, framesSeq, isPlaySubtags, aniDirValue); - if (tag) - params().tag(tag->name()); - m_framesSeq = framesSeq; - } - m_adjustFramesByTag = false; } + // m_selFrames is not empty if fromFrame/toFrame parameters are + // specified. + if (m_framesSeq.empty()) { + // Frames sequence to export + FramesSequence framesSeq; + Tag* tag = calculate_frames_sequence( + site, frames, framesSeq, isPlaySubtags, aniDirValue); + if (tag) + params().tag(tag->name()); + m_framesSeq = framesSeq; + } + m_adjustFramesByTag = false; + // Set other parameters params().aniDir(aniDirValue); if (!bounds.isEmpty())