Add support to specify tags in --filename-format option (related to #607)

Now we can use "{tag}" (or "{innertag}") and "{outertag}" in the filename
format.
This commit is contained in:
David Capello 2015-04-30 17:02:57 -03:00
parent c81aa88fc7
commit b519901cef
12 changed files with 134 additions and 46 deletions

View File

@ -369,10 +369,13 @@ void App::initialize(const AppOptions& options)
for (Layer* hide : layers)
hide->setVisible(hide == show);
fn = filename_formatter(format,
value.value(), show->name());
fmt = filename_formatter(format,
value.value(), show->name(), -1, false);
FilenameInfo fnInfo;
fnInfo
.filename(value.value())
.layerName(show->name());
fn = filename_formatter(format, fnInfo);
fmt = filename_formatter(format, fnInfo, false);
if (!cropParams.empty())
ctx->executeCommand(cropCommand, cropParams);

View File

@ -80,7 +80,7 @@ void FrameTagPropertiesCommand::onExecute(Context* context)
else if (m_tagId != NullId)
foundTag = sprite->frameTags().getById(m_tagId);
else
foundTag = get_shortest_tag(sprite, frame);
foundTag = sprite->frameTags().innerTag(frame);
if (!foundTag)
return;

View File

@ -76,7 +76,7 @@ void RemoveFrameTagCommand::onExecute(Context* context)
else if (m_tagId != NullId)
foundTag = sprite->frameTags().getById(m_tagId);
else
foundTag = get_shortest_tag(sprite, frame);
foundTag = sprite->frameTags().innerTag(frame);
if (!foundTag)
return;

View File

@ -25,6 +25,7 @@
#include "doc/algorithm/shrink_bounds.h"
#include "doc/cel.h"
#include "doc/dithering_method.h"
#include "doc/frame_tag.h"
#include "doc/image.h"
#include "doc/layer.h"
#include "doc/palette.h"
@ -343,11 +344,17 @@ void DocumentExporter::captureSamples(Samples& samples)
for (frame_t frame=frame_t(0);
frame<sprite->totalFrames(); ++frame) {
std::string filename =
filename_formatter(format,
doc->filename(),
layer ? layer->name(): "",
(sprite->totalFrames() > frame_t(1)) ? frame: frame_t(-1));
FrameTag* innerTag = sprite->frameTags().innerTag(frame);
FrameTag* outerTag = sprite->frameTags().outerTag(frame);
FilenameInfo fnInfo;
fnInfo
.filename(doc->filename())
.layerName(layer ? layer->name(): "")
.innerTagName(innerTag ? innerTag->name(): "")
.outerTagName(outerTag ? outerTag->name(): "")
.frame((sprite->totalFrames() > frame_t(1)) ? frame: frame_t(-1));
std::string filename = filename_formatter(format, fnInfo);
Sample sample(doc, sprite, layer, frame, filename, m_innerPadding);
Cel* cel = nullptr;

View File

@ -380,7 +380,10 @@ FileOp* fop_to_save_document(const Context* context, const Document* document,
// Save one frame
if (fop->document->sprite()->totalFrames() == 1) {
fn = filename_formatter(fn_format, fn);
FilenameInfo fnInfo;
fnInfo.filename(fn);
fn = filename_formatter(fn_format, fnInfo);
fop->seq.filename_list.push_back(fn);
}
// Save multiple frames
@ -401,16 +404,26 @@ FileOp* fop_to_save_document(const Context* context, const Document* document,
}
}
Sprite* spr = fop->document->sprite();
std::vector<char> buf(32);
std::sprintf(&buf[0], "{frame%0*d}", width, 0);
if (default_format)
fn_format = set_frame_format(fn_format, &buf[0]);
else if (fop->document->sprite()->totalFrames() > 1)
else if (spr->totalFrames() > 1)
fn_format = add_frame_format(fn_format, &buf[0]);
for (frame_t frame(0); frame<fop->document->sprite()->totalFrames(); ++frame) {
for (frame_t frame(0); frame<spr->totalFrames(); ++frame) {
FrameTag* innerTag = spr->frameTags().innerTag(frame);
FrameTag* outerTag = spr->frameTags().outerTag(frame);
FilenameInfo fnInfo;
fnInfo
.filename(fn)
.innerTagName(innerTag ? innerTag->name(): "")
.outerTagName(outerTag ? outerTag->name(): "")
.frame(start_from+frame);
std::string frame_fn =
filename_formatter(fn_format, fn, "", start_from+frame);
filename_formatter(fn_format, fnInfo);
fop->seq.filename_list.push_back(frame_fn);
}

View File

@ -21,10 +21,10 @@ namespace app {
std::string filename_formatter(
const std::string& format,
const std::string& filename,
const std::string& layerName,
int frame, bool replaceFrame)
FilenameInfo& info,
bool replaceFrame)
{
const std::string& filename = info.filename();
std::string path = base::get_file_path(filename);
if (path.empty())
path = ".";
@ -35,7 +35,10 @@ std::string filename_formatter(
base::replace_string(output, "{name}", base::get_file_name(filename));
base::replace_string(output, "{title}", base::get_file_title(filename));
base::replace_string(output, "{extension}", base::get_file_extension(filename));
base::replace_string(output, "{layer}", layerName);
base::replace_string(output, "{layer}", info.layerName());
base::replace_string(output, "{tag}", info.innerTagName());
base::replace_string(output, "{innertag}", info.innerTagName());
base::replace_string(output, "{outertag}", info.outerTagName());
if (replaceFrame) {
size_t i = output.find("{frame");
@ -43,11 +46,11 @@ std::string filename_formatter(
size_t j = output.find("}", i+6);
if (j != std::string::npos) {
std::string from = output.substr(i, j - i + 1);
if (frame >= 0) {
if (info.frame() >= 0) {
std::vector<char> to(32);
int offset = std::strtol(from.c_str()+6, NULL, 10);
std::sprintf(&to[0], "%0*d", (int(j)-int(i+6)), frame + offset);
std::sprintf(&to[0], "%0*d", (int(j)-int(i+6)), info.frame() + offset);
base::replace_string(output, from, &to[0]);
}
else

View File

@ -13,11 +13,52 @@
namespace app {
class FilenameInfo {
public:
FilenameInfo() : m_frame(-1) { }
const std::string& filename() const { return m_filename; }
const std::string& layerName() const { return m_layerName; }
const std::string& innerTagName() const { return m_innerTagName; }
const std::string& outerTagName() const { return m_outerTagName; }
int frame() const { return m_frame; }
FilenameInfo& filename(const std::string& value) {
m_filename = value;
return *this;
}
FilenameInfo& layerName(const std::string& value) {
m_layerName = value;
return *this;
}
FilenameInfo& innerTagName(const std::string& value) {
m_innerTagName = value;
return *this;
}
FilenameInfo& outerTagName(const std::string& value) {
m_outerTagName = value;
return *this;
}
FilenameInfo& frame(int value) {
m_frame = value;
return *this;
}
private:
std::string m_filename;
std::string m_layerName;
std::string m_innerTagName;
std::string m_outerTagName;
int m_frame;
};
std::string filename_formatter(
const std::string& format,
const std::string& filename,
const std::string& layerName = "",
int frame = -1,
FilenameInfo& info,
bool replaceFrame = true);
std::string set_frame_format(

View File

@ -20,27 +20,12 @@ const char* kLoopTagName = "Loop";
doc::FrameTag* get_animation_tag(const doc::Sprite* sprite, doc::frame_t frame)
{
doc::FrameTag* tag = get_shortest_tag(sprite, frame);
doc::FrameTag* tag = sprite->frameTags().innerTag(frame);
if (!tag)
tag = get_loop_tag(sprite);
return tag;
}
doc::FrameTag* get_shortest_tag(const doc::Sprite* sprite, doc::frame_t frame)
{
const doc::FrameTag* found = nullptr;
for (const doc::FrameTag* tag : sprite->frameTags()) {
if (frame >= tag->fromFrame() &&
frame <= tag->toFrame()) {
if (!found ||
(tag->toFrame() - tag->fromFrame()) < (found->toFrame() - found->fromFrame())) {
found = tag;
}
}
}
return const_cast<doc::FrameTag*>(found);
}
doc::FrameTag* get_loop_tag(const doc::Sprite* sprite)
{
// Get tag with special "Loop" name

View File

@ -20,7 +20,6 @@ namespace app {
doc::FrameTag* get_animation_tag(const doc::Sprite* sprite, doc::frame_t frame);
doc::FrameTag* get_loop_tag(const doc::Sprite* sprite);
doc::FrameTag* get_shortest_tag(const doc::Sprite* sprite, doc::frame_t frame);
doc::FrameTag* create_loop_tag(doc::frame_t from, doc::frame_t to);
} // namespace app

View File

@ -116,14 +116,17 @@ void UIContext::setActiveDocument(Document* document)
m_lastSelectedDoc = document;
DocumentView* docView = getFirstDocumentView(document);
ASSERT(docView);
if (docView)
if (docView) // The view can be null if we are in --batch mode
setActiveView(docView);
}
DocumentView* UIContext::getFirstDocumentView(Document* document) const
{
Workspace* workspace = App::instance()->getMainWindow()->getWorkspace();
MainWindow* mainWindow = App::instance()->getMainWindow();
if (!mainWindow) // Main window can be null if we are in --batch mode
return nullptr;
Workspace* workspace = mainWindow->getWorkspace();
for (WorkspaceView* view : *workspace) {
if (DocumentView* docView = dynamic_cast<DocumentView*>(view)) {
@ -133,7 +136,7 @@ DocumentView* UIContext::getFirstDocumentView(Document* document) const
}
}
return NULL;
return nullptr;
}
Editor* UIContext::activeEditor()

View File

@ -68,4 +68,34 @@ FrameTag* FrameTags::getById(ObjectId id) const
return nullptr;
}
FrameTag* FrameTags::innerTag(frame_t frame) const
{
const FrameTag* found = nullptr;
for (const FrameTag* tag : *this) {
if (frame >= tag->fromFrame() &&
frame <= tag->toFrame()) {
if (!found ||
(tag->toFrame() - tag->fromFrame()) < (found->toFrame() - found->fromFrame())) {
found = tag;
}
}
}
return const_cast<FrameTag*>(found);
}
FrameTag* FrameTags::outerTag(frame_t frame) const
{
const FrameTag* found = nullptr;
for (const FrameTag* tag : *this) {
if (frame >= tag->fromFrame() &&
frame <= tag->toFrame()) {
if (!found ||
(tag->toFrame() - tag->fromFrame()) > (found->toFrame() - found->fromFrame())) {
found = tag;
}
}
}
return const_cast<FrameTag*>(found);
}
} // namespace doc

View File

@ -9,10 +9,11 @@
#pragma once
#include "base/disable_copying.h"
#include "doc/frame.h"
#include "doc/object_id.h"
#include <vector>
#include <string>
#include <vector>
namespace doc {
@ -45,6 +46,9 @@ namespace doc {
std::size_t size() const { return m_tags.size(); }
bool empty() const { return m_tags.empty(); }
FrameTag* innerTag(frame_t frame) const;
FrameTag* outerTag(frame_t frame) const;
private:
Sprite* m_sprite;
List m_tags;