diff --git a/src/app/cli/cli_processor.cpp b/src/app/cli/cli_processor.cpp index e91eb849f..fc48a0fe9 100644 --- a/src/app/cli/cli_processor.cpp +++ b/src/app/cli/cli_processor.cpp @@ -28,6 +28,7 @@ #include "doc/frame_tag.h" #include "doc/frame_tags.h" #include "doc/layer.h" +#include "doc/selected_frames.h" namespace app { @@ -349,7 +350,7 @@ bool CliProcessor::openFile(CliOpenFile& cof) // Add document to exporter if (m_exporter) { FrameTag* frameTag = nullptr; - bool isTemporalTag = false; + SelectedFrames selFrames; if (cof.hasFrameTag()) { frameTag = doc->sprite()->frameTags().getByName(cof.frameTag); @@ -357,15 +358,14 @@ bool CliProcessor::openFile(CliOpenFile& cof) if (cof.hasFrameRange()) { // --frame-range with --frame-tag if (frameTag) { - frameTag = new FrameTag( + selFrames.insert( frameTag->fromFrame()+MID(0, cof.fromFrame, frameTag->frames()-1), frameTag->fromFrame()+MID(0, cof.toFrame, frameTag->frames()-1)); } // --frame-range without --frame-tag else { - frameTag = new FrameTag(cof.fromFrame, cof.toFrame); + selFrames.insert(cof.fromFrame, cof.toFrame); } - isTemporalTag = true; } if (!cof.importLayer.empty()) { @@ -377,14 +377,17 @@ bool CliProcessor::openFile(CliOpenFile& cof) } } if (foundLayer) - m_exporter->addDocument(doc, foundLayer, frameTag, isTemporalTag); + m_exporter->addDocument(doc, foundLayer, frameTag, + (!selFrames.empty() ? &selFrames: nullptr)); } else if (cof.splitLayers) { for (auto layer : doc->sprite()->allVisibleLayers()) - m_exporter->addDocument(doc, layer, frameTag, isTemporalTag); + m_exporter->addDocument(doc, layer, frameTag, + (!selFrames.empty() ? &selFrames: nullptr)); } else { - m_exporter->addDocument(doc, nullptr, frameTag, isTemporalTag); + m_exporter->addDocument(doc, nullptr, frameTag, + (!selFrames.empty() ? &selFrames: nullptr)); } } } diff --git a/src/app/commands/cmd_export_sprite_sheet.cpp b/src/app/commands/cmd_export_sprite_sheet.cpp index 806224ac2..294d50ecc 100644 --- a/src/app/commands/cmd_export_sprite_sheet.cpp +++ b/src/app/commands/cmd_export_sprite_sheet.cpp @@ -157,52 +157,36 @@ namespace { return true; } - class SelectedFrameTag { - public: - static frame_t From() { - // TODO the range of selected frames should be in doc::Site. + FrameTag* calculate_selected_frames(const Sprite* sprite, + const std::string& frameTagName, + SelectedFrames& selFrames) { + FrameTag* frameTag = nullptr; + + if (frameTagName == kSelectedFrames) { auto range = App::instance()->timeline()->range(); if (range.enabled()) { - return range.firstFrame(); + selFrames = range.selectedFrames(); } else if (current_editor) { - return current_editor->frame(); + selFrames.insert(current_editor->frame(), + current_editor->frame()); } else - return 0; + selFrames.insert(0, sprite->lastFrame()); } - - static frame_t To() { - auto range = App::instance()->timeline()->range(); - if (range.enabled()) { - return range.lastFrame(); - } - else if (current_editor) { - return current_editor->frame(); - } + else if (frameTagName != kAllFrames) { + frameTag = sprite->frameTags().getByName(frameTagName); + if (frameTag) + selFrames.insert(frameTag->fromFrame(), + frameTag->toFrame()); else - return 0; + selFrames.insert(0, sprite->lastFrame()); } + else + selFrames.insert(0, sprite->lastFrame()); - SelectedFrameTag() : m_frameTag(nullptr) { - } - - ~SelectedFrameTag() { - if (m_frameTag) { - m_frameTag->owner()->remove(m_frameTag); - delete m_frameTag; - } - } - - FrameTag* create(Sprite* sprite) { - m_frameTag = new FrameTag(From(), To()); - sprite->frameTags().add(m_frameTag); - return m_frameTag; - } - - private: - FrameTag* m_frameTag; - }; + return frameTag; + } class RestoreSelectedLayers { public: @@ -671,16 +655,12 @@ private: } void updateSizeFields() { - int nframes = m_sprite->totalFrames(); - std::string tagName = frameTagValue(); - if (tagName == kSelectedFrames) { - nframes = SelectedFrameTag::To() - SelectedFrameTag::From() + 1; - } - else { - FrameTag* frameTag = m_sprite->frameTags().getByName(tagName); - if (frameTag) - nframes = frameTag->toFrame() - frameTag->fromFrame() + 1; - } + SelectedFrames selFrames; + calculate_selected_frames(m_sprite, + frameTagValue(), + selFrames); + + frame_t nframes = selFrames.size(); Fit fit; if (bestFit()->isSelected()) { @@ -832,19 +812,12 @@ void ExportSpriteSheetCommand::onExecute(Context* context) return; // Do not overwrite } - // If the user want to export selected frames, we can create a - // temporal frame tag for that. - FrameTag* frameTag; - bool isTemporalTag = false; - SelectedFrameTag selectedFrameTag; - if (frameTagName == kSelectedFrames) { - frameTag = selectedFrameTag.create(sprite); - isTemporalTag = true; - } - else if (frameTagName != kAllFrames) - frameTag = sprite->frameTags().getByName(frameTagName); - else - frameTag = nullptr; + SelectedFrames selFrames; + FrameTag* frameTag = + calculate_selected_frames(sprite, frameTagName, selFrames); + + frame_t nframes = selFrames.size(); + ASSERT(nframes > 0); // If the user choose to render selected layers only, we can // temporaly make them visible and hide the other ones. @@ -864,9 +837,6 @@ void ExportSpriteSheetCommand::onExecute(Context* context) } } - int nframes = (frameTag ? frameTag->toFrame() - frameTag->fromFrame() + 1: - sprite->totalFrames()); - if (bestFit) { Fit fit = best_fit(sprite, nframes, borderPadding, shapePadding, innerPadding); columns = fit.columns; @@ -918,7 +888,8 @@ void ExportSpriteSheetCommand::onExecute(Context* context) exporter.setListLayers(true); if (listFrameTags) exporter.setListFrameTags(true); - exporter.addDocument(document, layer, frameTag, isTemporalTag); + exporter.addDocument(document, layer, frameTag, + (!selFrames.empty() ? &selFrames: nullptr)); base::UniquePtr newDocument(exporter.exportSheet()); if (!newDocument) diff --git a/src/app/document_exporter.cpp b/src/app/document_exporter.cpp index 11a0ee9b7..8f167d7bc 100644 --- a/src/app/document_exporter.cpp +++ b/src/app/document_exporter.cpp @@ -31,6 +31,7 @@ #include "doc/layer.h" #include "doc/palette.h" #include "doc/primitives.h" +#include "doc/selected_frames.h" #include "doc/sprite.h" #include "gfx/packing_rects.h" #include "gfx/size.h" @@ -106,9 +107,37 @@ private: typedef base::SharedPtr SampleBoundsPtr; +DocumentExporter::Item::Item(Document* doc, + doc::Layer* layer, + doc::FrameTag* frameTag, + doc::SelectedFrames* selFrames) + : doc(doc) + , layer(layer) + , frameTag(frameTag) + , selFrames(selFrames ? new doc::SelectedFrames(*selFrames): + nullptr) +{ +} + +DocumentExporter::Item::Item(Item&& other) + : doc(other.doc) + , layer(other.layer) + , frameTag(other.frameTag) + , selFrames(other.selFrames) +{ + other.selFrames = nullptr; +} + +DocumentExporter::Item::~Item() +{ + delete selFrames; +} + int DocumentExporter::Item::frames() const { - if (frameTag) { + if (selFrames) + return selFrames->size(); + else if (frameTag) { int result = frameTag->toFrame() - frameTag->fromFrame() + 1; return MID(1, result, doc->sprite()->totalFrames()); } @@ -116,20 +145,30 @@ int DocumentExporter::Item::frames() const return doc->sprite()->totalFrames(); } -int DocumentExporter::Item::fromFrame() const +doc::frame_t DocumentExporter::Item::firstFrame() const { - if (frameTag) - return MID(0, frameTag->fromFrame(), doc->sprite()->lastFrame()); + if (selFrames) + return selFrames->firstFrame(); + else if (frameTag) + return frameTag->fromFrame(); else return 0; } -int DocumentExporter::Item::toFrame() const +doc::SelectedFrames DocumentExporter::Item::getSelectedFrames() const { - if (frameTag) - return MID(0, frameTag->toFrame(), doc->sprite()->lastFrame()); - else - return doc->sprite()->lastFrame(); + if (selFrames) + return *selFrames; + + doc::SelectedFrames frames; + if (frameTag) { + frames.insert(MID(0, frameTag->fromFrame(), doc->sprite()->lastFrame()), + MID(0, frameTag->toFrame(), doc->sprite()->lastFrame())); + } + else { + frames.insert(0, doc->sprite()->lastFrame()); + } + return frames; } class DocumentExporter::Sample { @@ -360,14 +399,6 @@ DocumentExporter::DocumentExporter() { } -DocumentExporter::~DocumentExporter() -{ - for (auto& item : m_documents) { - if (item.temporalTag) - delete item.frameTag; - } -} - Document* DocumentExporter::exportSheet() { // We output the metadata to std::cout if the user didn't specify a file. @@ -445,12 +476,11 @@ void DocumentExporter::captureSamples(Samples& samples) doc->filename(), (frames > 1), // Has frames (layer != nullptr), // Has layer - (frameTag && !item.temporalTag)); // Has frame tag + (frameTag != nullptr)); // Has frame tag } - frame_t frameFirst = item.fromFrame(); - frame_t frameLast = item.toFrame(); - for (frame_t frame=frameFirst; frame<=frameLast; ++frame) { + frame_t frameFirst = item.firstFrame(); + for (frame_t frame : item.getSelectedFrames()) { FrameTag* innerTag = (frameTag ? frameTag: sprite->frameTags().innerTag(frame)); FrameTag* outerTag = sprite->frameTags().outerTag(frame); FilenameInfo fnInfo; diff --git a/src/app/document_exporter.h b/src/app/document_exporter.h index c24023b50..a59731d10 100644 --- a/src/app/document_exporter.h +++ b/src/app/document_exporter.h @@ -10,6 +10,7 @@ #include "app/sprite_sheet_type.h" #include "base/disable_copying.h" +#include "doc/frame.h" #include "doc/image_buffer.h" #include "doc/object_id.h" #include "gfx/fwd.h" @@ -24,6 +25,7 @@ namespace doc { class FrameTag; class Image; class Layer; + class SelectedFrames; } namespace app { @@ -38,7 +40,6 @@ namespace app { }; DocumentExporter(); - ~DocumentExporter(); DataFormat dataFormat() const { return m_dataFormat; } const std::string& dataFilename() { return m_dataFilename; } @@ -71,10 +72,10 @@ namespace app { void setListLayers(bool value) { m_listLayers = value; } void addDocument(Document* document, - doc::Layer* layer = nullptr, - doc::FrameTag* tag = nullptr, - bool temporalTag = false) { - m_documents.push_back(Item(document, layer, tag, temporalTag)); + doc::Layer* layer, + doc::FrameTag* tag, + doc::SelectedFrames* selFrames) { + m_documents.push_back(Item(document, layer, tag, selFrames)); } Document* exportSheet(); @@ -100,19 +101,22 @@ namespace app { Document* doc; doc::Layer* layer; doc::FrameTag* frameTag; - bool temporalTag; + doc::SelectedFrames* selFrames; Item(Document* doc, doc::Layer* layer, doc::FrameTag* frameTag, - bool temporalTag) - : doc(doc), layer(layer), frameTag(frameTag) - , temporalTag(temporalTag) { - } + doc::SelectedFrames* selFrames); + Item(Item&& other); + ~Item(); + + Item() = delete; + Item(const Item&) = delete; + Item& operator=(const Item&) = delete; int frames() const; - int fromFrame() const; - int toFrame() const; + doc::frame_t firstFrame() const; + doc::SelectedFrames getSelectedFrames() const; }; typedef std::vector Items;