mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-21 12:40:34 +00:00
Add "Trim Sprite" to DocExporter/Export Sprite Sheet/--trim-sprite CLI
This commit is contained in:
parent
f375ced883
commit
cd68a4fe0a
@ -59,7 +59,8 @@ AppOptions::AppOptions(int argc, const char* argv[])
|
||||
, 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"))
|
||||
, m_innerPadding(m_po.add("inner-padding").requiresValue("<value>").description("Add padding inside each frame"))
|
||||
, m_trim(m_po.add("trim").description("Trim all images before exporting"))
|
||||
, m_trim(m_po.add("trim").description("Trim whole sprite for --save-as\nor individual frames for --sheet"))
|
||||
, m_trimSprite(m_po.add("trim-sprite").description("Trim the whole sprite (for --save-as and --sheet)"))
|
||||
, m_trimByGrid(m_po.add("trim-by-grid").description("Trim all images by its correspondent grid boundaries before exporting"))
|
||||
, m_crop(m_po.add("crop").requiresValue("x,y,width,height").description("Crop all the images to the given rectangle"))
|
||||
, m_slice(m_po.add("slice").requiresValue("<name>").description("Crop the sprite to the given slice area"))
|
||||
|
@ -74,6 +74,7 @@ public:
|
||||
const Option& shapePadding() const { return m_shapePadding; }
|
||||
const Option& innerPadding() const { return m_innerPadding; }
|
||||
const Option& trim() const { return m_trim; }
|
||||
const Option& trimSprite() const { return m_trimSprite; }
|
||||
const Option& trimByGrid() const { return m_trimByGrid; }
|
||||
const Option& crop() const { return m_crop; }
|
||||
const Option& slice() const { return m_slice; }
|
||||
@ -135,6 +136,7 @@ private:
|
||||
Option& m_shapePadding;
|
||||
Option& m_innerPadding;
|
||||
Option& m_trim;
|
||||
Option& m_trimSprite;
|
||||
Option& m_trimByGrid;
|
||||
Option& m_crop;
|
||||
Option& m_slice;
|
||||
|
@ -331,6 +331,12 @@ void CliProcessor::process(Context* ctx)
|
||||
if (m_exporter)
|
||||
m_exporter->setTrimCels(true);
|
||||
}
|
||||
// --trim-sprite
|
||||
else if (opt == &m_options.trimSprite()) {
|
||||
cof.trim = true;
|
||||
if (m_exporter)
|
||||
m_exporter->setTrimSprite(true);
|
||||
}
|
||||
// --trim-by-grid
|
||||
else if (opt == &m_options.trimByGrid()) {
|
||||
cof.trim = cof.trimByGrid = true;
|
||||
|
@ -317,9 +317,6 @@ public:
|
||||
fill_frames_combobox(
|
||||
m_sprite, frames(), params.tag());
|
||||
|
||||
// TODO enable this when DocExporter support a global trim per sprite
|
||||
trimSpriteEnabled()->setVisible(false);
|
||||
|
||||
openGenerated()->setSelected(params.openGenerated());
|
||||
trimSpriteEnabled()->setSelected(params.trimSprite());
|
||||
trimEnabled()->setSelected(params.trim());
|
||||
@ -1121,6 +1118,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
|
||||
docPref.spriteSheet.borderPadding (params.borderPadding());
|
||||
docPref.spriteSheet.shapePadding (params.shapePadding());
|
||||
docPref.spriteSheet.innerPadding (params.innerPadding());
|
||||
docPref.spriteSheet.trimSprite (params.trimSprite());
|
||||
docPref.spriteSheet.trim (params.trim());
|
||||
docPref.spriteSheet.trimByGrid (params.trimByGrid());
|
||||
docPref.spriteSheet.extrude (params.extrude());
|
||||
|
@ -10,7 +10,6 @@
|
||||
#endif
|
||||
|
||||
#include "app/doc_api.h"
|
||||
#include "app/snap_to_grid.h"
|
||||
|
||||
#include "app/cmd/add_cel.h"
|
||||
#include "app/cmd/add_frame.h"
|
||||
@ -48,6 +47,7 @@
|
||||
#include "app/doc.h"
|
||||
#include "app/doc_undo.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/snap_to_grid.h"
|
||||
#include "app/transaction.h"
|
||||
#include "app/util/autocrop.h"
|
||||
#include "doc/algorithm/flip_image.h"
|
||||
@ -315,39 +315,7 @@ bool DocApi::cropCel(LayerImage* layer,
|
||||
|
||||
void DocApi::trimSprite(Sprite* sprite, const bool byGrid)
|
||||
{
|
||||
gfx::Rect bounds;
|
||||
|
||||
std::unique_ptr<Image> image_wrap(Image::create(sprite->spec()));
|
||||
Image* image = image_wrap.get();
|
||||
|
||||
render::Render render;
|
||||
|
||||
for (frame_t frame(0); frame<sprite->totalFrames(); ++frame) {
|
||||
render.renderSprite(image, sprite, frame);
|
||||
gfx::Rect frameBounds;
|
||||
doc::color_t refColor;
|
||||
|
||||
if (get_best_refcolor_for_trimming(image, refColor) &&
|
||||
doc::algorithm::shrink_bounds(image, frameBounds, refColor)) {
|
||||
bounds = bounds.createUnion(frameBounds);
|
||||
}
|
||||
|
||||
// TODO merge this code with the code in DocExporter::captureSamples()
|
||||
if (byGrid) {
|
||||
Doc* doc = m_document;
|
||||
const gfx::Rect& gridBounds = doc->sprite()->gridBounds();
|
||||
gfx::Point posTopLeft =
|
||||
snap_to_grid(gridBounds,
|
||||
bounds.origin(),
|
||||
PreferSnapTo::FloorGrid);
|
||||
gfx::Point posBottomRight =
|
||||
snap_to_grid(gridBounds,
|
||||
bounds.point2(),
|
||||
PreferSnapTo::CeilGrid);
|
||||
bounds = gfx::Rect(posTopLeft, posBottomRight);
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Rect bounds = get_trimmed_bounds(sprite, byGrid);
|
||||
if (!bounds.isEmpty())
|
||||
cropSprite(sprite, bounds);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "app/filename_formatter.h"
|
||||
#include "app/restore_visible_layers.h"
|
||||
#include "app/snap_to_grid.h"
|
||||
#include "doc/images_map.h"
|
||||
#include "app/util/autocrop.h"
|
||||
#include "base/convert_to.h"
|
||||
#include "base/fs.h"
|
||||
#include "base/fstream_path.h"
|
||||
@ -29,6 +29,7 @@
|
||||
#include "doc/cel.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/images_map.h"
|
||||
#include "doc/images_map.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/palette.h"
|
||||
#include "doc/primitives.h"
|
||||
@ -829,6 +830,10 @@ void DocExporter::captureSamples(Samples& samples,
|
||||
(tag != nullptr)); // Has tag
|
||||
}
|
||||
|
||||
gfx::Rect spriteBounds = sprite->bounds();
|
||||
if (m_trimSprite)
|
||||
spriteBounds = get_trimmed_bounds(sprite, m_trimByGrid);
|
||||
|
||||
frame_t outputFrame = 0;
|
||||
for (frame_t frame : item.getSelectedFrames()) {
|
||||
if (token.canceled())
|
||||
@ -911,7 +916,7 @@ void DocExporter::captureSamples(Samples& samples,
|
||||
else if (m_ignoreEmptyCels)
|
||||
refColor = sprite->transparentColor();
|
||||
|
||||
if (!algorithm::shrink_bounds(sampleRender.get(), frameBounds, refColor)) {
|
||||
if (!algorithm::shrink_bounds(sampleRender.get(), spriteBounds, frameBounds, refColor)) {
|
||||
// If shrink_bounds() returns false, it's because the whole
|
||||
// image is transparent (equal to the mask color).
|
||||
|
||||
@ -950,7 +955,11 @@ void DocExporter::captureSamples(Samples& samples,
|
||||
}
|
||||
sample.setTrimmedBounds(frameBounds);
|
||||
}
|
||||
else if (m_trimSprite)
|
||||
sample.setTrimmedBounds(spriteBounds);
|
||||
}
|
||||
else if (m_trimSprite)
|
||||
sample.setTrimmedBounds(spriteBounds);
|
||||
|
||||
samples.addSample(sample);
|
||||
|
||||
|
@ -9,12 +9,17 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/util/autocrop.h"
|
||||
|
||||
#include "app/snap_to_grid.h"
|
||||
#include "doc/algorithm/shrink_bounds.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "app/util/autocrop.h"
|
||||
#include "render/render.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -254,4 +259,42 @@ bool get_best_refcolor_for_trimming(
|
||||
return true;
|
||||
}
|
||||
|
||||
gfx::Rect get_trimmed_bounds(
|
||||
const doc::Sprite* sprite,
|
||||
const bool byGrid)
|
||||
{
|
||||
gfx::Rect bounds;
|
||||
|
||||
std::unique_ptr<Image> image_wrap(Image::create(sprite->spec()));
|
||||
Image* image = image_wrap.get();
|
||||
|
||||
render::Render render;
|
||||
|
||||
for (frame_t frame(0); frame<sprite->totalFrames(); ++frame) {
|
||||
render.renderSprite(image, sprite, frame);
|
||||
|
||||
gfx::Rect frameBounds;
|
||||
doc::color_t refColor;
|
||||
if (get_best_refcolor_for_trimming(image, refColor) &&
|
||||
doc::algorithm::shrink_bounds(image, frameBounds, refColor)) {
|
||||
bounds = bounds.createUnion(frameBounds);
|
||||
}
|
||||
|
||||
// TODO merge this code with the code in DocExporter::captureSamples()
|
||||
if (byGrid) {
|
||||
const gfx::Rect& gridBounds = sprite->gridBounds();
|
||||
gfx::Point posTopLeft =
|
||||
snap_to_grid(gridBounds,
|
||||
bounds.origin(),
|
||||
PreferSnapTo::FloorGrid);
|
||||
gfx::Point posBottomRight =
|
||||
snap_to_grid(gridBounds,
|
||||
bounds.point2(),
|
||||
PreferSnapTo::CeilGrid);
|
||||
bounds = gfx::Rect(posTopLeft, posBottomRight);
|
||||
}
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -10,9 +10,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "doc/color.h"
|
||||
#include "gfx/rect.h"
|
||||
|
||||
namespace doc {
|
||||
class Image;
|
||||
class Sprite;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
@ -29,6 +31,10 @@ namespace app {
|
||||
doc::Image* image,
|
||||
doc::color_t& refColor);
|
||||
|
||||
gfx::Rect get_trimmed_bounds(
|
||||
const doc::Sprite* sprite,
|
||||
const bool byGrid);
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user