Merge branch '1.0'

Conflicts:
	src/app/commands/cmd_undo.cpp
	src/app/document_exporter.cpp
	src/app/document_exporter.h
This commit is contained in:
David Capello 2015-02-02 11:44:09 -03:00
commit 0aedc7c74e
8 changed files with 110 additions and 64 deletions

View File

@ -1,5 +1,5 @@
/* Aseprite
* Copyright (C) 2001-2014 David Capello
* Copyright (C) 2001-2015 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -219,6 +219,7 @@ void App::initialize(const AppOptions& options)
PRINTF("Processing options...\n");
bool ignoreEmpty = false;
bool trim = false;
// Open file specified in the command line
if (!options.values().empty()) {
@ -273,6 +274,10 @@ void App::initialize(const AppOptions& options)
else if (opt == &options.ignoreEmpty()) {
ignoreEmpty = true;
}
// --trim
else if (opt == &options.trim()) {
trim = true;
}
// --filename-format
else if (opt == &options.filenameFormat()) {
filenameFormat = value.value();
@ -291,7 +296,10 @@ void App::initialize(const AppOptions& options)
std::string format = filenameFormat;
Command* command = CommandsModule::instance()->getCommandByName(CommandId::SaveFileCopyAs);
Command* saveAsCommand = CommandsModule::instance()->getCommandByName(CommandId::SaveFileCopyAs);
Command* trimCommand = CommandsModule::instance()->getCommandByName(CommandId::AutocropSprite);
Command* undoCommand = CommandsModule::instance()->getCommandByName(CommandId::Undo);
if (splitLayersSaveAs) {
std::vector<Layer*> layers;
doc->sprite()->getLayersList(layers);
@ -314,10 +322,21 @@ void App::initialize(const AppOptions& options)
fmt = filename_formatter(format,
value.value(), show->name(), -1, false);
// TODO --trim command with --save-as doesn't make too
// much sense as we lost the trim rectangle
// information (e.g. we don't have sheet .json) Also,
// we should trim each frame individually (a process
// that can be done only in fop_operate()).
if (trim)
ctx->executeCommand(trimCommand);
Params params;
params.set("filename", fn.c_str());
params.set("filename-format", fmt.c_str());
ctx->executeCommand(command, &params);
ctx->executeCommand(saveAsCommand, &params);
if (trim) // Undo trim command
ctx->executeCommand(undoCommand);
}
}
else {
@ -330,10 +349,16 @@ void App::initialize(const AppOptions& options)
layer->setVisible(layer->name() == importLayerSaveAs);
}
if (trim)
ctx->executeCommand(trimCommand);
Params params;
params.set("filename", value.value().c_str());
params.set("filename-format", format.c_str());
ctx->executeCommand(command, &params);
ctx->executeCommand(saveAsCommand, &params);
if (trim) // Undo trim command
ctx->executeCommand(undoCommand);
}
}
}
@ -406,12 +431,15 @@ void App::initialize(const AppOptions& options)
}
// Export
if (m_exporter != NULL) {
if (m_exporter) {
PRINTF("Exporting sheet...\n");
if (ignoreEmpty)
m_exporter->setIgnoreEmptyCels(true);
if (trim)
m_exporter->setTrimCels(true);
m_exporter->exportSheet();
m_exporter.reset(NULL);
}

View File

@ -49,6 +49,7 @@ AppOptions::AppOptions(int argc, const char* argv[])
, 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_ignoreEmpty(m_po.add("ignore-empty").description("Do not export empty frames/cels"))
, m_trim(m_po.add("trim").description("Trim all images before exporting"))
, m_filenameFormat(m_po.add("filename-format").requiresValue("<fmt>").description("Special format to generate filenames"))
, 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"))

View File

@ -57,6 +57,7 @@ public:
const Option& splitLayers() const { return m_splitLayers; }
const Option& importLayer() const { return m_importLayer; }
const Option& ignoreEmpty() const { return m_ignoreEmpty; }
const Option& trim() const { return m_trim; }
const Option& filenameFormat() const { return m_filenameFormat; }
bool hasExporterParams() const;
@ -85,6 +86,7 @@ private:
Option& m_splitLayers;
Option& m_importLayer;
Option& m_ignoreEmpty;
Option& m_trim;
Option& m_filenameFormat;
Option& m_verbose;

View File

@ -105,8 +105,9 @@ void UndoCommand::onExecute(Context* context)
}
}
StatusBar::instance()
->showTip(1000, "%s %s",
StatusBar* statusbar = StatusBar::instance();
if (statusbar)
statusbar->showTip(1000, "%s %s",
(m_type == Undo ? "Undid": "Redid"),
(m_type == Undo ?
undo->nextUndoLabel().c_str():

View File

@ -59,7 +59,10 @@ public:
m_sprite(sprite),
m_layer(layer),
m_frame(frame),
m_filename(filename) {
m_filename(filename),
m_originalSize(sprite->width(), sprite->height()),
m_trimmedBounds(0, 0, sprite->width(), sprite->height()),
m_inTextureBounds(0, 0, sprite->width(), sprite->height()) {
}
Document* document() const { return m_document; }
@ -128,37 +131,39 @@ public:
const Layer* oldLayer = NULL;
gfx::Point framePt(0, 0);
gfx::Size rowSize(0, 0);
for (auto& sample : samples) {
const Sprite* sprite = sample.sprite();
const Layer* layer = sample.layer();
gfx::Size size(sprite->width(), sprite->height());
gfx::Size size = sample.trimmedBounds().getSize();
if (oldSprite) {
// If the user didn't specified a width for the texture, we put
// each sprite/layer in a different row.
if (width == 0) {
// New sprite or layer, go to next row.
if (oldSprite != sprite || oldLayer != layer) {
framePt.x = 0;
framePt.y += oldSprite->height(); // We're skipping the previous sprite height
}
}
// When a texture width is specified, we can put different
// sprites/layers in each row until we reach the texture
// right-border.
else if (framePt.x+size.w > width) {
framePt.x = 0;
framePt.y += oldSprite->height();
// TODO framePt.y+size.h > height ?
// If the user didn't specify a width for the texture, we put
// each sprite/layer in a different row.
if (width == 0) {
// New sprite or layer, go to next row.
if (oldSprite != sprite || oldLayer != layer) {
framePt.x = 0;
framePt.y += rowSize.h;
rowSize = size;
}
}
// When a texture width is specified, we can put different
// sprites/layers in each row until we reach the texture
// right-border.
else if (framePt.x+size.w > width) {
framePt.x = 0;
framePt.y += rowSize.h;
rowSize = size;
}
}
sample.setOriginalSize(size);
sample.setTrimmedBounds(gfx::Rect(gfx::Point(0, 0), size));
sample.setInTextureBounds(gfx::Rect(framePt, size));
// Next frame position.
framePt.x += size.w;
rowSize = rowSize.createUnion(size);
oldSprite = sprite;
oldLayer = layer;
@ -172,15 +177,8 @@ public:
void layoutSamples(Samples& samples, int& width, int& height) override {
gfx::PackingRects pr;
for (auto& sample : samples) {
const Sprite* sprite = sample.sprite();
gfx::Size size(sprite->width(), sprite->height());
sample.setOriginalSize(size);
sample.setTrimmedBounds(gfx::Rect(gfx::Point(0, 0), size));
pr.add(size);
}
for (auto& sample : samples)
pr.add(sample.trimmedBounds().getSize());
if (width == 0 || height == 0) {
gfx::Size sz = pr.bestFit();
@ -208,6 +206,7 @@ DocumentExporter::DocumentExporter()
, m_scale(1.0)
, m_scaleMode(DefaultScaleMode)
, m_ignoreEmptyCels(false)
, m_trimCels(false)
{
}
@ -266,7 +265,6 @@ void DocumentExporter::exportSheet()
void DocumentExporter::captureSamples(Samples& samples)
{
ImageBufferPtr checkEmptyImageBuf;
std::vector<char> buf(32);
for (auto& item : m_documents) {
@ -298,29 +296,38 @@ void DocumentExporter::captureSamples(Samples& samples)
Sample sample(doc, sprite, layer, frame, filename);
if (m_ignoreEmptyCels) {
if (m_ignoreEmptyCels || m_trimCels) {
if (layer && layer->isImage() && !layer->cel(frame)) {
// Empty cel this sample completely
continue;
}
base::UniquePtr<Image> checkEmptyImage(
base::UniquePtr<Image> sampleRender(
Image::create(sprite->pixelFormat(),
sprite->width(),
sprite->height(),
checkEmptyImageBuf));
m_sampleRenderBuf));
checkEmptyImage->setMaskColor(sprite->transparentColor());
clear_image(checkEmptyImage, sprite->transparentColor());
renderSample(sample, checkEmptyImage, 0, 0);
sampleRender->setMaskColor(sprite->transparentColor());
clear_image(sampleRender, sprite->transparentColor());
renderSample(sample, sampleRender);
gfx::Rect frameBounds;
if (!algorithm::shrink_bounds(checkEmptyImage, frameBounds,
sprite->transparentColor())) {
doc::color_t refColor;
if (m_trimCels)
refColor = get_pixel(sampleRender, 0, 0);
else if (m_ignoreEmptyCels)
refColor = sprite->transparentColor();
if (!algorithm::shrink_bounds(sampleRender, frameBounds, refColor)) {
// If shrink_bounds returns false, it's because the whole
// image is transparent (equal to the mask color).
continue;
}
if (m_trimCels)
sample.setTrimmedBounds(frameBounds);
}
samples.addSample(sample);
@ -385,10 +392,7 @@ void DocumentExporter::renderTexture(const Samples& samples, Image* textureImage
DitheringMethod::NONE).execute(UIContext::instance());
}
int x = sample.inTextureBounds().x - sample.trimmedBounds().x;
int y = sample.inTextureBounds().y - sample.trimmedBounds().y;
renderSample(sample, textureImage, x, y);
renderSample(sample, textureImage);
}
}
@ -443,17 +447,18 @@ void DocumentExporter::createDataFile(const Samples& samples, std::ostream& os,
<< "}\n";
}
void DocumentExporter::renderSample(const Sample& sample, doc::Image* dst, int x, int y)
void DocumentExporter::renderSample(const Sample& sample, doc::Image* dst)
{
render::Render render;
gfx::Clip clip(
sample.inTextureBounds().x,
sample.inTextureBounds().y, sample.trimmedBounds());
if (sample.layer()) {
render.renderLayer(dst, sample.layer(), sample.frame(),
gfx::Clip(x, y, sample.sprite()->bounds()));
render.renderLayer(dst, sample.layer(), sample.frame(), clip);
}
else {
render.renderSprite(dst, sample.sprite(), sample.frame(),
gfx::Clip(x, y, sample.sprite()->bounds()));
render.renderSprite(dst, sample.sprite(), sample.frame(), clip);
}
}

View File

@ -1,5 +1,5 @@
/* Aseprite
* Copyright (C) 2001-2014 David Capello
* Copyright (C) 2001-2015 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -21,11 +21,12 @@
#pragma once
#include "base/disable_copying.h"
#include "doc/image_buffer.h"
#include "gfx/fwd.h"
#include <iosfwd>
#include <vector>
#include <string>
#include <vector>
namespace doc {
class Image;
@ -93,6 +94,10 @@ namespace app {
m_ignoreEmptyCels = ignore;
}
void setTrimCels(bool trim) {
m_trimCels = trim;
}
void setFilenameFormat(const std::string& format) {
m_filenameFormat = format;
}
@ -114,7 +119,7 @@ namespace app {
Document* createEmptyTexture(const Samples& samples);
void renderTexture(const Samples& samples, doc::Image* textureImage);
void createDataFile(const Samples& samples, std::ostream& os, doc::Image* textureImage);
void renderSample(const Sample& sample, doc::Image* dst, int x, int y);
void renderSample(const Sample& sample, doc::Image* dst);
class Item {
public:
@ -136,8 +141,10 @@ namespace app {
double m_scale;
ScaleMode m_scaleMode;
bool m_ignoreEmptyCels;
bool m_trimCels;
Items m_documents;
std::string m_filenameFormat;
doc::ImageBufferPtr m_sampleRenderBuf;
DISABLE_COPYING(DocumentExporter);
};

View File

@ -86,11 +86,11 @@ namespace app {
double progress; // Progress (1.0 is ready).
IFileOpProgress* progressInterface;
std::string error; // Error string.
bool done : 1; // True if the operation finished.
bool stop : 1; // Force the break of the operation.
bool oneframe : 1; // Load just one frame (in formats
// that support animation like
// GIF/FLI/ASE).
bool done; // True if the operation finished.
bool stop; // Force the break of the operation.
bool oneframe; // Load just one frame (in formats
// that support animation like
// GIF/FLI/ASE).
// Data for sequences.
struct {

View File

@ -386,12 +386,14 @@ bool UISettingsImpl::getAutoSelectLayer()
app::Color UISettingsImpl::getFgColor()
{
return ColorBar::instance()->getFgColor();
ColorBar* colorbar = ColorBar::instance();
return colorbar ? colorbar->getFgColor(): app::Color::fromMask();
}
app::Color UISettingsImpl::getBgColor()
{
return ColorBar::instance()->getBgColor();
ColorBar* colorbar = ColorBar::instance();
return colorbar ? colorbar->getBgColor(): app::Color::fromMask();
}
tools::Tool* UISettingsImpl::getCurrentTool()