Fix "Export Sprite Sheet" for selected frames/layers

Now we can export a give group, layer, and (non-adjacent) selected
layers/frames.
This commit is contained in:
David Capello 2016-09-13 16:10:36 -03:00
parent 6bbd6b27ff
commit 3a9c2e8325
4 changed files with 111 additions and 103 deletions

View File

@ -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));
}
}
}

View File

@ -157,53 +157,37 @@ 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
selFrames.insert(0, sprite->lastFrame());
}
else
return 0;
}
selFrames.insert(0, sprite->lastFrame());
SelectedFrameTag() : m_frameTag(nullptr) {
return frameTag;
}
~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;
};
class RestoreSelectedLayers {
public:
~RestoreSelectedLayers() {
@ -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<Document> newDocument(exporter.exportSheet());
if (!newDocument)

View File

@ -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<SampleBounds> 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;

View File

@ -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<Item> Items;