mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-23 09:41:04 +00:00
Add the logic side to export the selection only (fix #645)
This commit is contained in:
parent
3c3d2dafe6
commit
a13423bd70
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -47,6 +47,7 @@ FileOpROI CliOpenFile::roi() const
|
||||
selFrames.insert(fromFrame, toFrame);
|
||||
|
||||
return FileOpROI(document,
|
||||
gfx::Rect(),
|
||||
slice,
|
||||
tag,
|
||||
selFrames,
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "base/fs.h"
|
||||
#include "base/scoped_value.h"
|
||||
#include "base/thread.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/tag.h"
|
||||
#include "fmt/format.h"
|
||||
@ -204,7 +205,12 @@ void SaveFileBaseCommand::saveDocumentInBackground(
|
||||
}
|
||||
}
|
||||
|
||||
FileOpROI roi(document, params().slice(), params().tag(),
|
||||
gfx::Rect bounds;
|
||||
if (params().bounds.isSet())
|
||||
bounds = params().bounds();
|
||||
|
||||
FileOpROI roi(document, bounds,
|
||||
params().slice(), params().tag(),
|
||||
m_selFrames, m_adjustFramesByTag);
|
||||
|
||||
std::unique_ptr<FileOp> fop(
|
||||
@ -346,6 +352,7 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||
std::string frames = kAllFrames;
|
||||
bool applyPixelRatio = false;
|
||||
double scale = params().scale();
|
||||
gfx::Rect bounds = params().bounds();
|
||||
doc::AniDir aniDirValue = params().aniDir();
|
||||
bool isForTwitter = false;
|
||||
|
||||
@ -382,6 +389,13 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||
if (params().scale.isSet()) win.setResizeScale(scale);
|
||||
if (params().aniDir.isSet()) win.setAniDir(aniDirValue);
|
||||
|
||||
if (params().slice.isSet()) win.setArea(params().slice());
|
||||
else if (params().bounds.isSet() &&
|
||||
doc->isMaskVisible() &&
|
||||
doc->mask()->bounds() == params().bounds()) {
|
||||
win.setArea(kSelectedCanvas);
|
||||
}
|
||||
|
||||
win.remapWindow();
|
||||
load_window_pos(&win, "ExportFile");
|
||||
again:;
|
||||
@ -410,6 +424,9 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||
layers = win.layersValue();
|
||||
frames = win.framesValue();
|
||||
scale = win.resizeValue();
|
||||
params().slice(win.areaValue()); // Set slice
|
||||
if (win.areaValue() == kSelectedCanvas && doc->isMaskVisible())
|
||||
bounds = doc->mask()->bounds();
|
||||
applyPixelRatio = win.applyPixelRatio();
|
||||
aniDirValue = win.aniDirValue();
|
||||
isForTwitter = win.isForTwitter();
|
||||
@ -480,8 +497,10 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||
m_adjustFramesByTag = false;
|
||||
}
|
||||
|
||||
// Set ani dir
|
||||
// Set other parameters
|
||||
params().aniDir(aniDirValue);
|
||||
if (!bounds.isEmpty())
|
||||
params().bounds(bounds);
|
||||
|
||||
// TODO This should be set as options for the specific encoder
|
||||
GifEncoderDurationFix fixGif(isForTwitter);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "doc/anidir.h"
|
||||
#include "doc/selected_frames.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/rect.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -31,6 +32,7 @@ namespace app {
|
||||
Param<doc::frame_t> toFrame { this, 0, { "toFrame", "to-frame" } };
|
||||
Param<bool> ignoreEmpty { this, false, "ignoreEmpty" };
|
||||
Param<double> scale { this, 1.0, "scale" };
|
||||
Param<gfx::Rect> bounds { this, gfx::Rect(), "bounds" };
|
||||
};
|
||||
|
||||
class SaveFileBaseCommand : public CommandWithNewParams<SaveFileParams> {
|
||||
|
@ -65,9 +65,9 @@ public:
|
||||
ASSERT(m_doc && m_sprite);
|
||||
}
|
||||
|
||||
void setSliceBounds(const gfx::Rect& sliceBounds) {
|
||||
m_spec.setWidth(sliceBounds.w * m_scale.x);
|
||||
m_spec.setHeight(sliceBounds.h * m_scale.y);
|
||||
void setSpecSize(const gfx::Size& size) {
|
||||
m_spec.setWidth(size.w * m_scale.x);
|
||||
m_spec.setHeight(size.h * m_scale.y);
|
||||
}
|
||||
|
||||
void setUnscaledImage(const doc::frame_t frame,
|
||||
@ -234,7 +234,7 @@ int save_document(Context* context, Doc* document)
|
||||
std::unique_ptr<FileOp> fop(
|
||||
FileOp::createSaveDocumentOperation(
|
||||
context,
|
||||
FileOpROI(document, "", "", SelectedFrames(), false),
|
||||
FileOpROI(document, gfx::Rect(), "", "", SelectedFrames(), false),
|
||||
document->filename(), "",
|
||||
false));
|
||||
if (!fop)
|
||||
@ -270,11 +270,13 @@ FileOpROI::FileOpROI()
|
||||
}
|
||||
|
||||
FileOpROI::FileOpROI(const Doc* doc,
|
||||
const gfx::Rect& bounds,
|
||||
const std::string& sliceName,
|
||||
const std::string& tagName,
|
||||
const doc::SelectedFrames& selFrames,
|
||||
const bool adjustByTag)
|
||||
: m_document(doc)
|
||||
, m_bounds(bounds)
|
||||
, m_slice(nullptr)
|
||||
, m_tag(nullptr)
|
||||
, m_selFrames(selFrames)
|
||||
@ -917,23 +919,35 @@ void FileOp::operate(IFileOpProgress* progress)
|
||||
|
||||
frame_t outputFrame = 0;
|
||||
for (frame_t frame : m_roi.selectedFrames()) {
|
||||
// Draw the "frame" in "m_seq.image"
|
||||
gfx::Rect bounds;
|
||||
|
||||
// Export bounds of specific slice
|
||||
if (m_roi.slice()) {
|
||||
const SliceKey* key = m_roi.slice()->getByFrame(frame);
|
||||
if (!key || key->isEmpty())
|
||||
continue; // Skip frame because there is no slice key
|
||||
|
||||
bounds = key->bounds();
|
||||
}
|
||||
// Export specific bounds
|
||||
else if (!m_roi.bounds().isEmpty()) {
|
||||
bounds = m_roi.bounds();
|
||||
}
|
||||
|
||||
// Draw the "frame" in "m_seq.image" with the given bounds
|
||||
// (bounds can be the selection bounds or a slice key bounds)
|
||||
if (!bounds.isEmpty()) {
|
||||
if (m_abstractImage)
|
||||
m_abstractImage->setSliceBounds(key->bounds());
|
||||
m_abstractImage->setSpecSize(bounds.size());
|
||||
|
||||
m_seq.image.reset(
|
||||
Image::create(sprite->pixelFormat(),
|
||||
key->bounds().w,
|
||||
key->bounds().h));
|
||||
bounds.w,
|
||||
bounds.h));
|
||||
|
||||
render.renderSprite(
|
||||
m_seq.image.get(), sprite, frame,
|
||||
gfx::Clip(gfx::Point(0, 0), key->bounds()));
|
||||
gfx::Clip(gfx::Point(0, 0), bounds));
|
||||
}
|
||||
else {
|
||||
render.renderSprite(m_seq.image.get(), sprite, frame);
|
||||
|
@ -72,12 +72,14 @@ namespace app {
|
||||
public:
|
||||
FileOpROI();
|
||||
FileOpROI(const Doc* doc,
|
||||
const gfx::Rect& bounds,
|
||||
const std::string& sliceName,
|
||||
const std::string& tagName,
|
||||
const doc::SelectedFrames& selFrames,
|
||||
const bool adjustByTag);
|
||||
|
||||
const Doc* document() const { return m_document; }
|
||||
const gfx::Rect& bounds() const { return m_bounds; }
|
||||
doc::Slice* slice() const { return m_slice; }
|
||||
doc::Tag* tag() const { return m_tag; }
|
||||
doc::frame_t fromFrame() const { return m_selFrames.firstFrame(); }
|
||||
@ -90,6 +92,7 @@ namespace app {
|
||||
|
||||
private:
|
||||
const Doc* m_document;
|
||||
gfx::Rect m_bounds;
|
||||
doc::Slice* m_slice;
|
||||
doc::Tag* m_tag;
|
||||
doc::SelectedFrames m_selFrames;
|
||||
|
@ -153,6 +153,11 @@ void ExportFileWindow::setResizeScale(double scale)
|
||||
resize()->setValue(fmt::format("{:.2f}", 100.0 * scale));
|
||||
}
|
||||
|
||||
void ExportFileWindow::setArea(const std::string& areaValue)
|
||||
{
|
||||
area()->setValue(areaValue);
|
||||
}
|
||||
|
||||
void ExportFileWindow::setAniDir(const doc::AniDir aniDir)
|
||||
{
|
||||
anidir()->setSelectedItemIndex(int(aniDir));
|
||||
|
@ -37,6 +37,7 @@ namespace app {
|
||||
|
||||
void setOutputFilename(const std::string& pathAndFilename);
|
||||
void setResizeScale(const double scale);
|
||||
void setArea(const std::string& area);
|
||||
void setAniDir(const doc::AniDir aniDir);
|
||||
|
||||
obs::signal<std::string()> SelectOutputFile;
|
||||
|
Loading…
x
Reference in New Issue
Block a user