Add --ignore-empty command line option (close #549)

This option can be used to avoid exporting empty frames/cels.
This commit is contained in:
David Capello 2014-11-30 10:23:11 -03:00
parent aee7eb7bd4
commit b7d86e596a
5 changed files with 61 additions and 7 deletions

View File

@ -210,6 +210,8 @@ void App::initialize(int argc, const char* argv[])
// Procress options // Procress options
PRINTF("Processing options...\n"); PRINTF("Processing options...\n");
bool ignoreEmpty = false;
// Open file specified in the command line // Open file specified in the command line
if (!options.values().empty()) { if (!options.values().empty()) {
Console console; Console console;
@ -258,6 +260,10 @@ void App::initialize(int argc, const char* argv[])
importLayer = value.value(); importLayer = value.value();
importLayerSaveAs = value.value(); importLayerSaveAs = value.value();
} }
// --ignore-empty
else if (opt == &options.ignoreEmpty()) {
ignoreEmpty = true;
}
// --save-as <filename> // --save-as <filename>
else if (opt == &options.saveAs()) { else if (opt == &options.saveAs()) {
Document* doc = NULL; Document* doc = NULL;
@ -380,6 +386,9 @@ void App::initialize(int argc, const char* argv[])
if (m_exporter != NULL) { if (m_exporter != NULL) {
PRINTF("Exporting sheet...\n"); PRINTF("Exporting sheet...\n");
if (ignoreEmpty)
m_exporter->setIgnoreEmptyCels(true);
m_exporter->exportSheet(); m_exporter->exportSheet();
m_exporter.reset(NULL); m_exporter.reset(NULL);
} }

View File

@ -48,6 +48,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_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_splitLayers(m_po.add("split-layers").description("Import each layer of the next given sprite as\na separated image in the sheet"))
, m_importLayer(m_po.add("import-layer").requiresValue("<name>").description("Import just one layer of the next given sprite")) , m_importLayer(m_po.add("import-layer").requiresValue("<name>").description("Import just one layer of the next given sprite"))
, m_ignoreEmpty(m_po.add("ignore-empty").description("Do not export empty frames/cels"))
, m_verbose(m_po.add("verbose").description("Explain what is being done")) , m_verbose(m_po.add("verbose").description("Explain what is being done"))
, m_help(m_po.add("help").mnemonic('?').description("Display this help and exits")) , m_help(m_po.add("help").mnemonic('?').description("Display this help and exits"))
, m_version(m_po.add("version").description("Output version information and exit")) , m_version(m_po.add("version").description("Output version information and exit"))

View File

@ -56,6 +56,7 @@ public:
const Option& sheetPack() const { return m_sheetPack; } const Option& sheetPack() const { return m_sheetPack; }
const Option& splitLayers() const { return m_splitLayers; } const Option& splitLayers() const { return m_splitLayers; }
const Option& importLayer() const { return m_importLayer; } const Option& importLayer() const { return m_importLayer; }
const Option& ignoreEmpty() const { return m_ignoreEmpty; }
bool hasExporterParams() const; bool hasExporterParams() const;
@ -82,6 +83,7 @@ private:
Option& m_sheetPack; Option& m_sheetPack;
Option& m_splitLayers; Option& m_splitLayers;
Option& m_importLayer; Option& m_importLayer;
Option& m_ignoreEmpty;
Option& m_verbose; Option& m_verbose;
Option& m_help; Option& m_help;

View File

@ -32,6 +32,7 @@
#include "base/unique_ptr.h" #include "base/unique_ptr.h"
#include "gfx/packing_rects.h" #include "gfx/packing_rects.h"
#include "gfx/size.h" #include "gfx/size.h"
#include "raster/algorithm/shrink_bounds.h"
#include "raster/cel.h" #include "raster/cel.h"
#include "raster/dithering_method.h" #include "raster/dithering_method.h"
#include "raster/image.h" #include "raster/image.h"
@ -205,6 +206,7 @@ DocumentExporter::DocumentExporter()
, m_texturePack(false) , m_texturePack(false)
, m_scale(1.0) , m_scale(1.0)
, m_scaleMode(DefaultScaleMode) , m_scaleMode(DefaultScaleMode)
, m_ignoreEmptyCels(false)
{ {
} }
@ -264,6 +266,7 @@ void DocumentExporter::exportSheet()
void DocumentExporter::captureSamples(Samples& samples) void DocumentExporter::captureSamples(Samples& samples)
{ {
ImageBufferPtr checkEmptyImageBuf;
std::vector<char> buf(32); std::vector<char> buf(32);
for (auto& item : m_documents) { for (auto& item : m_documents) {
@ -289,7 +292,35 @@ void DocumentExporter::captureSamples(Samples& samples)
+ "." + base::get_file_extension(filename)); + "." + base::get_file_extension(filename));
} }
samples.addSample(Sample(doc, sprite, layer, frame, filename)); Sample sample(doc, sprite, layer, frame, filename);
if (m_ignoreEmptyCels) {
if (layer && layer->isImage() &&
!static_cast<LayerImage*>(layer)->getCel(frame)) {
// Empty cel this sample completely
continue;
}
base::UniquePtr<Image> checkEmptyImage(
Image::create(sprite->pixelFormat(),
sprite->width(),
sprite->height(),
checkEmptyImageBuf));
checkEmptyImage->setMaskColor(sprite->transparentColor());
clear_image(checkEmptyImage, sprite->transparentColor());
renderSample(sample, checkEmptyImage, 0, 0);
gfx::Rect frameBounds;
if (!algorithm::shrink_bounds(checkEmptyImage, frameBounds,
sprite->transparentColor())) {
// If shrink_bounds returns false, it's because the whole
// image is transparent (equal to the mask color).
continue;
}
}
samples.addSample(sample);
} }
} }
} }
@ -355,12 +386,7 @@ void DocumentExporter::renderTexture(const Samples& samples, Image* textureImage
int x = sample.inTextureBounds().x - sample.trimmedBounds().x; int x = sample.inTextureBounds().x - sample.trimmedBounds().x;
int y = sample.inTextureBounds().y - sample.trimmedBounds().y; int y = sample.inTextureBounds().y - sample.trimmedBounds().y;
if (sample.layer()) { renderSample(sample, textureImage, x, y);
layer_render(sample.layer(), textureImage, x, y, sample.frame());
}
else {
sample.sprite()->render(textureImage, x, y, sample.frame());
}
} }
} }
@ -415,4 +441,14 @@ void DocumentExporter::createDataFile(const Samples& samples, std::ostream& os,
<< "}\n"; << "}\n";
} }
void DocumentExporter::renderSample(const Sample& sample, raster::Image* dst, int x, int y)
{
if (sample.layer()) {
layer_render(sample.layer(), dst, x, y, sample.frame());
}
else {
sample.sprite()->render(dst, x, y, sample.frame());
}
}
} // namespace app } // namespace app

View File

@ -89,6 +89,10 @@ namespace app {
m_scaleMode = mode; m_scaleMode = mode;
} }
void setIgnoreEmptyCels(bool ignore) {
m_ignoreEmptyCels = ignore;
}
void addDocument(Document* document, raster::Layer* layer = NULL) { void addDocument(Document* document, raster::Layer* layer = NULL) {
m_documents.push_back(Item(document, layer)); m_documents.push_back(Item(document, layer));
} }
@ -106,6 +110,7 @@ namespace app {
Document* createEmptyTexture(const Samples& samples); Document* createEmptyTexture(const Samples& samples);
void renderTexture(const Samples& samples, raster::Image* textureImage); void renderTexture(const Samples& samples, raster::Image* textureImage);
void createDataFile(const Samples& samples, std::ostream& os, raster::Image* textureImage); void createDataFile(const Samples& samples, std::ostream& os, raster::Image* textureImage);
void renderSample(const Sample& sample, raster::Image* dst, int x, int y);
class Item { class Item {
public: public:
@ -126,6 +131,7 @@ namespace app {
bool m_texturePack; bool m_texturePack;
double m_scale; double m_scale;
ScaleMode m_scaleMode; ScaleMode m_scaleMode;
bool m_ignoreEmptyCels;
Items m_documents; Items m_documents;
DISABLE_COPYING(DocumentExporter); DISABLE_COPYING(DocumentExporter);