mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-14 03:40:55 +00:00
Add support to export all/selected/one layer/frame/frame tag
This commit includes support to export tagged frames using the command line --frame-tag option. Fix #415, fix #570, fix #607, fix #745
This commit is contained in:
parent
d1799c037a
commit
ff9693b29d
@ -227,6 +227,8 @@
|
||||
<option id="shape_padding" type="int" default="0" />
|
||||
<option id="inner_padding" type="int" default="0" />
|
||||
<option id="open_generated" type="bool" default="false" />
|
||||
<option id="layer" type="std::string" />
|
||||
<option id="frame_tag" type="std::string" />
|
||||
</section>
|
||||
<section id="import_sprite_sheet">
|
||||
<option id="bounds" type="gfx::Rect" default="gfx::Rect(0, 0, 16, 16)" />
|
||||
|
@ -31,6 +31,12 @@
|
||||
<hbox id="best_fit_filler" />
|
||||
<check cell_hspan="3" id="best_fit" text="Best fit for texture" />
|
||||
|
||||
<label text="Layers:" />
|
||||
<combobox id="layers" text="" cell_hspan="3" />
|
||||
|
||||
<label text="Frames:" />
|
||||
<combobox id="frames" text="" cell_hspan="3" />
|
||||
|
||||
<label text="Save As:" />
|
||||
<button id="image_filename" cell_hspan="3" />
|
||||
|
||||
|
@ -227,6 +227,7 @@ void App::initialize(const AppOptions& options)
|
||||
std::string importLayer;
|
||||
std::string importLayerSaveAs;
|
||||
std::string filenameFormat;
|
||||
std::string frameTagName;
|
||||
|
||||
for (const auto& value : options.values()) {
|
||||
const AppOptions::Option* opt = value.option();
|
||||
@ -281,6 +282,10 @@ void App::initialize(const AppOptions& options)
|
||||
importLayer = value.value();
|
||||
importLayerSaveAs = value.value();
|
||||
}
|
||||
// --frame-tag <tag-name>
|
||||
else if (opt == &options.frameTag()) {
|
||||
frameTagName = value.value();
|
||||
}
|
||||
// --ignore-empty
|
||||
else if (opt == &options.ignoreEmpty()) {
|
||||
ignoreEmpty = true;
|
||||
@ -450,6 +455,10 @@ void App::initialize(const AppOptions& options)
|
||||
getRecentFiles()->addRecentFile(filename.c_str());
|
||||
|
||||
if (m_exporter != NULL) {
|
||||
FrameTag* frameTag = nullptr;
|
||||
if (!frameTagName.empty())
|
||||
frameTag = doc->sprite()->frameTags().getByName(frameTagName);
|
||||
|
||||
if (!importLayer.empty()) {
|
||||
std::vector<Layer*> layers;
|
||||
doc->sprite()->getLayersList(layers);
|
||||
@ -462,16 +471,16 @@ void App::initialize(const AppOptions& options)
|
||||
}
|
||||
}
|
||||
if (foundLayer)
|
||||
m_exporter->addDocument(doc, foundLayer);
|
||||
m_exporter->addDocument(doc, foundLayer, frameTag);
|
||||
}
|
||||
else if (splitLayers) {
|
||||
std::vector<Layer*> layers;
|
||||
doc->sprite()->getLayersList(layers);
|
||||
for (auto layer : layers)
|
||||
m_exporter->addDocument(doc, layer);
|
||||
m_exporter->addDocument(doc, layer, frameTag);
|
||||
}
|
||||
else
|
||||
m_exporter->addDocument(doc);
|
||||
m_exporter->addDocument(doc, nullptr, frameTag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@ AppOptions::AppOptions(int argc, const char* argv[])
|
||||
, m_sheetPack(m_po.add("sheet-pack").description("Use a packing algorithm to avoid waste of space\nin the texture"))
|
||||
, m_splitLayers(m_po.add("split-layers").description("Import each layer of the next given sprite as\na separated image in the sheet"))
|
||||
, m_layer(m_po.add("layer").alias("import-layer").requiresValue("<name>").description("Include just the given layer in the sheet"))
|
||||
, m_frameTag(m_po.add("frame-tag").requiresValue("<name>").description("Include tagged frames in the sheet"))
|
||||
, m_ignoreEmpty(m_po.add("ignore-empty").description("Do not export empty frames/cels"))
|
||||
, m_borderPadding(m_po.add("border-padding").requiresValue("<value>").description("Add padding on the texture borders"))
|
||||
, m_shapePadding(m_po.add("shape-padding").requiresValue("<value>").description("Add padding between frames"))
|
||||
|
@ -46,6 +46,7 @@ public:
|
||||
const Option& sheetPack() const { return m_sheetPack; }
|
||||
const Option& splitLayers() const { return m_splitLayers; }
|
||||
const Option& layer() const { return m_layer; }
|
||||
const Option& frameTag() const { return m_frameTag; }
|
||||
const Option& ignoreEmpty() const { return m_ignoreEmpty; }
|
||||
const Option& borderPadding() const { return m_borderPadding; }
|
||||
const Option& shapePadding() const { return m_shapePadding; }
|
||||
@ -80,6 +81,7 @@ private:
|
||||
Option& m_sheetPack;
|
||||
Option& m_splitLayers;
|
||||
Option& m_layer;
|
||||
Option& m_frameTag;
|
||||
Option& m_ignoreEmpty;
|
||||
Option& m_borderPadding;
|
||||
Option& m_shapePadding;
|
||||
|
@ -17,12 +17,18 @@
|
||||
#include "app/document_exporter.h"
|
||||
#include "app/file/file.h"
|
||||
#include "app/file_selector.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/main_window.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/ui/timeline.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/convert_to.h"
|
||||
#include "base/fs.h"
|
||||
#include "base/path.h"
|
||||
#include "doc/frame_tag.h"
|
||||
#include "doc/layer.h"
|
||||
|
||||
#include "generated_export_sprite_sheet.h"
|
||||
|
||||
@ -35,6 +41,11 @@ using namespace ui;
|
||||
|
||||
namespace {
|
||||
|
||||
static const char* kAllLayers = "";
|
||||
static const char* kAllFrames = "";
|
||||
static const char* kSelectedLayers = "**selected-layers**";
|
||||
static const char* kSelectedFrames = "**selected-frames**";
|
||||
|
||||
struct Fit {
|
||||
int width;
|
||||
int height;
|
||||
@ -49,8 +60,7 @@ namespace {
|
||||
|
||||
// Calculate best size for the given sprite
|
||||
// TODO this function was programmed in ten minutes, please optimize it
|
||||
Fit best_fit(Sprite* sprite, int borderPadding, int shapePadding, int innerPadding) {
|
||||
int nframes = sprite->totalFrames();
|
||||
Fit best_fit(Sprite* sprite, int nframes, int borderPadding, int shapePadding, int innerPadding) {
|
||||
int framew = sprite->width()+2*innerPadding;
|
||||
int frameh = sprite->height()+2*innerPadding;
|
||||
Fit result(framew*nframes, frameh, nframes, std::numeric_limits<int>::max());
|
||||
@ -101,9 +111,8 @@ namespace {
|
||||
return result;
|
||||
}
|
||||
|
||||
Fit calculate_sheet_size(Sprite* sprite, int columns, int borderPadding, int shapePadding, int innerPadding) {
|
||||
int nframes = sprite->totalFrames();
|
||||
|
||||
Fit calculate_sheet_size(Sprite* sprite, int nframes, int columns,
|
||||
int borderPadding, int shapePadding, int innerPadding) {
|
||||
columns = MID(1, columns, nframes);
|
||||
int rows = ((nframes/columns) + ((nframes%columns) > 0 ? 1: 0));
|
||||
|
||||
@ -136,10 +145,118 @@ namespace {
|
||||
return true;
|
||||
}
|
||||
|
||||
class SelectedFrameTag {
|
||||
public:
|
||||
static frame_t From() {
|
||||
// TODO the range of selected frames should be in doc::Site.
|
||||
DocumentRange range = App::instance()->getMainWindow()->getTimeline()->range();
|
||||
if (range.enabled()) {
|
||||
return range.frameBegin();
|
||||
}
|
||||
else if (current_editor) {
|
||||
return current_editor->frame();
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static frame_t To() {
|
||||
DocumentRange range = App::instance()->getMainWindow()->getTimeline()->range();
|
||||
if (range.enabled()) {
|
||||
return range.frameEnd();
|
||||
}
|
||||
else if (current_editor) {
|
||||
return current_editor->frame();
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
class SelectedLayers {
|
||||
public:
|
||||
~SelectedLayers() {
|
||||
for (auto item : m_restore)
|
||||
item.first->setVisible(item.second);
|
||||
}
|
||||
|
||||
void showSelectedLayers(Sprite* sprite) {
|
||||
// TODO the range of selected frames should be in doc::Site.
|
||||
DocumentRange range = App::instance()->getMainWindow()->getTimeline()->range();
|
||||
if (!range.enabled()) {
|
||||
if (current_editor) {
|
||||
ASSERT(current_editor->sprite() == sprite);
|
||||
range.startRange(sprite->layerToIndex(current_editor->layer()),
|
||||
current_editor->frame(), DocumentRange::kCels);
|
||||
range.endRange(sprite->layerToIndex(current_editor->layer()),
|
||||
current_editor->frame());
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<Layer*> layers;
|
||||
sprite->getLayersList(layers);
|
||||
for (int i=0; i<int(layers.size()); ++i) {
|
||||
Layer* layer = layers[i];
|
||||
bool selected = range.inRange(LayerIndex(i));
|
||||
|
||||
if (selected != layer->isVisible()) {
|
||||
m_restore.push_back(std::make_pair(layer, layer->isVisible()));
|
||||
layer->setVisible(selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<Layer*, bool> > m_restore;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class ExportSpriteSheetWindow : public app::gen::ExportSpriteSheet {
|
||||
public:
|
||||
class LayerItem : public ListItem {
|
||||
public:
|
||||
LayerItem(Layer* layer)
|
||||
: ListItem("Layer: " + layer->name())
|
||||
, m_layer(layer) {
|
||||
}
|
||||
Layer* layer() const { return m_layer; }
|
||||
private:
|
||||
Layer* m_layer;
|
||||
};
|
||||
|
||||
class TagItem : public ListItem {
|
||||
public:
|
||||
TagItem(FrameTag* tag)
|
||||
: ListItem("Tag: " + tag->name())
|
||||
, m_tag(tag) {
|
||||
}
|
||||
FrameTag* tag() const { return m_tag; }
|
||||
private:
|
||||
FrameTag* m_tag;
|
||||
};
|
||||
|
||||
ExportSpriteSheetWindow(Document* doc, Sprite* sprite,
|
||||
DocumentPreferences& docPref)
|
||||
: m_sprite(sprite)
|
||||
@ -160,6 +277,30 @@ public:
|
||||
if (m_docPref.spriteSheet.type() != app::gen::SpriteSheetType::NONE)
|
||||
sheetType()->setSelectedItemIndex((int)m_docPref.spriteSheet.type()-1);
|
||||
|
||||
layers()->addItem("Visible layers");
|
||||
int i = layers()->addItem("Selected layers");
|
||||
if (m_docPref.spriteSheet.layer() == kSelectedLayers)
|
||||
layers()->setSelectedItemIndex(i);
|
||||
{
|
||||
std::vector<Layer*> layersList;
|
||||
m_sprite->getLayersList(layersList);
|
||||
for (Layer* layer : layersList) {
|
||||
i = layers()->addItem(new LayerItem(layer));
|
||||
if (m_docPref.spriteSheet.layer() == layer->name())
|
||||
layers()->setSelectedItemIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
frames()->addItem("All frames");
|
||||
i = frames()->addItem("Selected frames");
|
||||
if (m_docPref.spriteSheet.frameTag() == kSelectedFrames)
|
||||
frames()->setSelectedItemIndex(i);
|
||||
for (FrameTag* tag : m_sprite->frameTags()) {
|
||||
i = frames()->addItem(new TagItem(tag));
|
||||
if (m_docPref.spriteSheet.frameTag() == tag->name())
|
||||
frames()->setSelectedItemIndex(i);
|
||||
}
|
||||
|
||||
openGenerated()->setSelected(m_docPref.spriteSheet.openGenerated());
|
||||
|
||||
borderPadding()->setTextf("%d", m_docPref.spriteSheet.borderPadding());
|
||||
@ -225,6 +366,7 @@ public:
|
||||
dataEnabled()->Click.connect(Bind<void>(&ExportSpriteSheetWindow::onDataEnabledChange, this));
|
||||
dataFilename()->Click.connect(Bind<void>(&ExportSpriteSheetWindow::onDataFilename, this));
|
||||
paddingEnabled()->Click.connect(Bind<void>(&ExportSpriteSheetWindow::onPaddingEnabledChange, this));
|
||||
frames()->Change.connect(Bind<void>(&ExportSpriteSheetWindow::onFramesChange, this));
|
||||
|
||||
onSheetTypeChange();
|
||||
onFileNamesChange();
|
||||
@ -296,6 +438,24 @@ public:
|
||||
return openGenerated()->isSelected();
|
||||
}
|
||||
|
||||
std::string layerValue() {
|
||||
if (LayerItem* item = dynamic_cast<LayerItem*>(layers()->getSelectedItem()))
|
||||
return item->layer()->name();
|
||||
else if (layers()->getSelectedItemIndex() == 1)
|
||||
return kSelectedLayers;
|
||||
else
|
||||
return kAllLayers;
|
||||
}
|
||||
|
||||
std::string frameTagValue() {
|
||||
if (TagItem* item = dynamic_cast<TagItem*>(frames()->getSelectedItem()))
|
||||
return item->tag()->name();
|
||||
else if (frames()->getSelectedItemIndex() == 1)
|
||||
return kSelectedFrames;
|
||||
else
|
||||
return kAllFrames;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void onExport() {
|
||||
@ -387,6 +547,10 @@ protected:
|
||||
updateSizeFields();
|
||||
}
|
||||
|
||||
void onFramesChange() {
|
||||
updateSizeFields();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void resize() {
|
||||
@ -396,15 +560,25 @@ private:
|
||||
}
|
||||
|
||||
void updateSizeFields() {
|
||||
Fit fit;
|
||||
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;
|
||||
}
|
||||
|
||||
Fit fit;
|
||||
if (bestFit()->isSelected()) {
|
||||
fit = best_fit(m_sprite,
|
||||
borderPaddingValue(), shapePaddingValue(), innerPaddingValue());
|
||||
fit = best_fit(m_sprite, nframes,
|
||||
borderPaddingValue(), shapePaddingValue(), innerPaddingValue());
|
||||
}
|
||||
else {
|
||||
fit = calculate_sheet_size(
|
||||
m_sprite, columnsValue(),
|
||||
m_sprite, nframes, columnsValue(),
|
||||
borderPaddingValue(),
|
||||
shapePaddingValue(),
|
||||
innerPaddingValue());
|
||||
@ -491,6 +665,8 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
|
||||
docPref.spriteSheet.shapePadding(window.shapePaddingValue());
|
||||
docPref.spriteSheet.innerPadding(window.innerPaddingValue());
|
||||
docPref.spriteSheet.openGenerated(window.openGeneratedValue());
|
||||
docPref.spriteSheet.layer(window.layerValue());
|
||||
docPref.spriteSheet.frameTag(window.frameTagValue());
|
||||
|
||||
// Default preferences for future sprites
|
||||
DocumentPreferences& defPref(Preferences::instance().document(nullptr));
|
||||
@ -508,6 +684,8 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
|
||||
bool bestFit = docPref.spriteSheet.bestFit();
|
||||
std::string filename = docPref.spriteSheet.textureFilename();
|
||||
std::string dataFilename = docPref.spriteSheet.dataFilename();
|
||||
std::string layerName = docPref.spriteSheet.layer();
|
||||
std::string frameTagName = docPref.spriteSheet.frameTag();
|
||||
int borderPadding = docPref.spriteSheet.borderPadding();
|
||||
int shapePadding = docPref.spriteSheet.shapePadding();
|
||||
int innerPadding = docPref.spriteSheet.innerPadding();
|
||||
@ -521,20 +699,55 @@ 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;
|
||||
|
||||
// If the user choose to render selected layers only, we can
|
||||
// temporaly make them visible and hide the other ones.
|
||||
Layer* layer = nullptr;
|
||||
SelectedLayers layersVisibility;
|
||||
if (layerName == kSelectedLayers) {
|
||||
layersVisibility.showSelectedLayers(sprite);
|
||||
}
|
||||
else {
|
||||
// TODO add a getLayerByName
|
||||
std::vector<Layer*> layers;
|
||||
sprite->getLayersList(layers);
|
||||
for (Layer* l : layers) {
|
||||
if (l->name() == layerName) {
|
||||
layer = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nframes = (frameTag ? frameTag->toFrame() - frameTag->fromFrame() + 1:
|
||||
sprite->totalFrames());
|
||||
|
||||
if (bestFit) {
|
||||
Fit fit = best_fit(sprite, borderPadding, shapePadding, innerPadding);
|
||||
Fit fit = best_fit(sprite, nframes, borderPadding, shapePadding, innerPadding);
|
||||
columns = fit.columns;
|
||||
width = fit.width;
|
||||
height = fit.height;
|
||||
}
|
||||
|
||||
frame_t nframes = sprite->totalFrames();
|
||||
int sheet_w = 0;
|
||||
int sheet_h = 0;
|
||||
|
||||
switch (type) {
|
||||
case app::gen::SpriteSheetType::HORIZONTAL_STRIP:
|
||||
columns = nframes;
|
||||
columns = sprite->totalFrames();
|
||||
break;
|
||||
case app::gen::SpriteSheetType::VERTICAL_STRIP:
|
||||
columns = 1;
|
||||
@ -545,7 +758,10 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
|
||||
break;
|
||||
}
|
||||
|
||||
Fit fit = calculate_sheet_size(sprite, columns,
|
||||
Fit fit = calculate_sheet_size(
|
||||
sprite,
|
||||
nframes,
|
||||
columns,
|
||||
borderPadding, shapePadding, innerPadding);
|
||||
columns = fit.columns;
|
||||
if (sheet_w == 0) sheet_w = fit.width;
|
||||
@ -561,7 +777,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
|
||||
exporter.setBorderPadding(borderPadding);
|
||||
exporter.setShapePadding(shapePadding);
|
||||
exporter.setInnerPadding(innerPadding);
|
||||
exporter.addDocument(document);
|
||||
exporter.addDocument(document, layer, frameTag, isTemporalTag);
|
||||
|
||||
base::UniquePtr<Document> newDocument(exporter.exportSheet());
|
||||
if (!newDocument)
|
||||
|
@ -86,6 +86,32 @@ private:
|
||||
|
||||
typedef base::SharedPtr<SampleBounds> SampleBoundsPtr;
|
||||
|
||||
int DocumentExporter::Item::frames() const
|
||||
{
|
||||
if (frameTag) {
|
||||
int result = frameTag->toFrame() - frameTag->fromFrame() + 1;
|
||||
return MID(1, result, doc->sprite()->totalFrames());
|
||||
}
|
||||
else
|
||||
return doc->sprite()->totalFrames();
|
||||
}
|
||||
|
||||
int DocumentExporter::Item::fromFrame() const
|
||||
{
|
||||
if (frameTag)
|
||||
return MID(0, frameTag->fromFrame(), doc->sprite()->lastFrame());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DocumentExporter::Item::toFrame() const
|
||||
{
|
||||
if (frameTag)
|
||||
return MID(0, frameTag->toFrame(), doc->sprite()->lastFrame());
|
||||
else
|
||||
return doc->sprite()->lastFrame();
|
||||
}
|
||||
|
||||
class DocumentExporter::Sample {
|
||||
public:
|
||||
Sample(Document* document, Sprite* sprite, Layer* layer,
|
||||
@ -336,24 +362,29 @@ void DocumentExporter::captureSamples(Samples& samples)
|
||||
Document* doc = item.doc;
|
||||
Sprite* sprite = doc->sprite();
|
||||
Layer* layer = item.layer;
|
||||
bool hasFrames = (doc->sprite()->totalFrames() > frame_t(1));
|
||||
bool hasLayer = (layer != NULL);
|
||||
FrameTag* frameTag = item.frameTag;
|
||||
int frames = item.frames();
|
||||
bool hasFrames = (frames > 1);
|
||||
bool hasLayer = (layer != nullptr);
|
||||
bool hasFrameTag = (frameTag && !item.temporalTag);
|
||||
|
||||
std::string format = m_filenameFormat;
|
||||
if (format.empty()) {
|
||||
if (hasFrames && hasLayer)
|
||||
format = "{title} ({layer}) {frame}.{extension}";
|
||||
else if (hasFrames)
|
||||
format = "{title} {frame}.{extension}";
|
||||
else if (hasLayer)
|
||||
format = "{title} ({layer}).{extension}";
|
||||
if (hasFrames || hasLayer | hasFrameTag) {
|
||||
format = "{title}";
|
||||
if (hasLayer ) format += " ({layer})";
|
||||
if (hasFrameTag) format += " #{tag}";
|
||||
if (hasFrames ) format += " {frame}";
|
||||
format += ".{extension}";
|
||||
}
|
||||
else
|
||||
format = "{name}";
|
||||
}
|
||||
|
||||
for (frame_t frame=frame_t(0);
|
||||
frame<sprite->totalFrames(); ++frame) {
|
||||
FrameTag* innerTag = sprite->frameTags().innerTag(frame);
|
||||
frame_t frameFirst = item.fromFrame();
|
||||
frame_t frameLast = item.toFrame();
|
||||
for (frame_t frame=frameFirst; frame<=frameLast; ++frame) {
|
||||
FrameTag* innerTag = (frameTag ? frameTag: sprite->frameTags().innerTag(frame));
|
||||
FrameTag* outerTag = sprite->frameTags().outerTag(frame);
|
||||
FilenameInfo fnInfo;
|
||||
fnInfo
|
||||
@ -361,7 +392,7 @@ void DocumentExporter::captureSamples(Samples& samples)
|
||||
.layerName(layer ? layer->name(): "")
|
||||
.innerTagName(innerTag ? innerTag->name(): "")
|
||||
.outerTagName(outerTag ? outerTag->name(): "")
|
||||
.frame((sprite->totalFrames() > frame_t(1)) ? frame: frame_t(-1));
|
||||
.frame((frames > 1) ? frame-frameFirst: frame_t(-1));
|
||||
|
||||
std::string filename = filename_formatter(format, fnInfo);
|
||||
|
||||
@ -389,7 +420,9 @@ void DocumentExporter::captureSamples(Samples& samples)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(done);
|
||||
// "done" variable can be false here, e.g. when we export a
|
||||
// frame tag and the first linked cel is outside the tag range.
|
||||
ASSERT(done || (!done && frameTag));
|
||||
}
|
||||
|
||||
if (!done && (m_ignoreEmptyCels || m_trimCels)) {
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <vector>
|
||||
|
||||
namespace doc {
|
||||
class FrameTag;
|
||||
class Image;
|
||||
class Layer;
|
||||
}
|
||||
@ -60,8 +61,11 @@ namespace app {
|
||||
void setTrimCels(bool trim) { m_trimCels = trim; }
|
||||
void setFilenameFormat(const std::string& format) { m_filenameFormat = format; }
|
||||
|
||||
void addDocument(Document* document, doc::Layer* layer = NULL) {
|
||||
m_documents.push_back(Item(document, layer));
|
||||
void addDocument(Document* document,
|
||||
doc::Layer* layer = nullptr,
|
||||
doc::FrameTag* tag = nullptr,
|
||||
bool temporalTag = false) {
|
||||
m_documents.push_back(Item(document, layer, tag, temporalTag));
|
||||
}
|
||||
|
||||
Document* exportSheet();
|
||||
@ -83,9 +87,20 @@ namespace app {
|
||||
public:
|
||||
Document* doc;
|
||||
doc::Layer* layer;
|
||||
Item(Document* doc, doc::Layer* layer)
|
||||
: doc(doc), layer(layer) {
|
||||
doc::FrameTag* frameTag;
|
||||
bool temporalTag;
|
||||
|
||||
Item(Document* doc,
|
||||
doc::Layer* layer,
|
||||
doc::FrameTag* frameTag,
|
||||
bool temporalTag)
|
||||
: doc(doc), layer(layer), frameTag(frameTag)
|
||||
, temporalTag(temporalTag) {
|
||||
}
|
||||
|
||||
int frames() const;
|
||||
int fromFrame() const;
|
||||
int toFrame() const;
|
||||
};
|
||||
typedef std::vector<Item> Items;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user