mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-23 00:40:04 +00:00
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:
parent
6bbd6b27ff
commit
3a9c2e8325
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<Document> newDocument(exporter.exportSheet());
|
||||
if (!newDocument)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user