Skip to content

Commit

Permalink
Added pack methods rows and columns
Browse files Browse the repository at this point in the history
  • Loading branch information
houmain committed Feb 7, 2023
1 parent bddb766 commit 917a396
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 11 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ set(SOURCES
src/pack_compact.cpp
src/pack_single.cpp
src/pack_keep.cpp
src/pack_lines.cpp
src/output.cpp
src/globbing.cpp
src/debug.cpp
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ The following table contains a list of all definitions, with the subject each af
| Definition |Subject| Arguments | Description |
| -------------- |-------| -------------| ----------- |
| **output** |sprite | path | Sets the output texture's _path_. It can describe an un-/bounded sequence of files (e.g. "sheet{0-}.png").
| pack |output | pack-method | Sets the method, which is used for placing the sprites on the output textures:<br/>- _binpack_ : Tries to reduce the texture size, while keeping the sprites' (trimmed) rectangles apart (default).<br/>- _compact_ : Tries to reduce the texture size, while keeping the sprites' convex outlines apart.<br/>- _single_ : Put each sprite on its own texture.<br/>
| pack |output | pack-method | Sets the method, which is used for placing the sprites on the output textures:<br/>- _binpack_ : Tries to reduce the texture size, while keeping the sprites' (trimmed) rectangles apart (default).<br/>- _compact_ : Tries to reduce the texture size, while keeping the sprites' convex outlines apart.<br/>- _rows_ : Layout sprites in simple rows.<br/>- _columns_ : Layout sprites in simple columns.<br/>- _single_ : Put each sprite on its own texture.<br/>- _keep_ : Keep sprite at same position as in source (ignores most constraints).
| width |output | width | Sets a fixed output texture width.
| height |output | height | Sets a fixed output texture height.
| max-width |output | width | Sets a maximum output texture width.
Expand All @@ -234,7 +234,7 @@ The following table contains a list of all definitions, with the subject each af
| padding |output | [pixels], [pixels] | Sets the space between two sprites / the space between a sprite and the texture's border.
| duplicates |output | dedupe-mode | Sets how identical sprites should be processed:<br/>- _keep_ : Disable duplicate detection (default).<br/>- _share_ : Identical sprites should share pixels on the output texture.<br/>- _drop_ : Duplicates should be dropped.
| alpha |output | alpha-mode<br/>[color] | Sets an operation depending on the pixels' alpha values:<br/>- _keep_ : Keep source color and alpha.<br/>- _clear_ : Set color of fully transparent pixels to black.<br/>- _bleed_ : Set color of fully transparent pixels to their nearest non-fully transparent pixel's color.<br/>- _premultiply_ : Premultiply colors with alpha values.<br/>- _colorkey_ : Replace fully transparent pixels with the specified _color_ and make all others opaque.
| scalings |output | ([filter-mode] scale)+ | Specifies one or more factors for which a respectively scaled output should be generated, with an optional explicit filter-mode:<br/>- _box_: A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios.<br/>- _bilinear_: On upsampling, produces same results as bilinear texture filtering.<br/>- _cubicspline_: The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque.<br/>- _catmullrom_: An interpolating cubic spline.<br/>- _mitchell_: Mitchell-Netrevalli filter with B=1/3, C=1/3.
| scalings |output | ([scale-filter] scale)+ | Specifies one or more factors for which a respectively scaled output should be generated, with an optional explicit scale-filter:<br/>- _box_: A trapezoid with 1-pixel wide ramps.<br/>- _triangle_: A triangle function (same results as bilinear texture filtering).<br/>- _cubicspline_: A cubic b-spline (gaussian-esque).<br/>- _catmullrom_: An interpolating cubic spline.<br/>- _mitchell_: Mitchell-Netrevalli filter with B=1/3, C=1/3.
| layers |output/input| suffix+ | Specifies the number of layers and their filename suffixes (e.g. "-diffuse", "-normals", ...). Only the first layer is considered when packing, others get identical _rects_.
| **input** |- | path | Adds a new input file at _path_. It can contain wildcards (e.g. "sprites/**/*.png") or it can describe an un-/bounded sequence of files (e.g. "frames_{0-}.png, frames_{0001-0013}.png").
| path |input | path | A _path_ which should be prepended to the input's path.
Expand All @@ -258,7 +258,7 @@ The following table contains a list of all definitions, with the subject each af
| trim-margin |sprite | [pixels] | Sets a number of transparent pixel rows around the sprite, which should not be removed by trimming.
| crop |sprite | [boolean] | Sets whether the sprite's rectangle should be reduced to the trimmed bounds.
| crop-pivot |sprite | [boolean] | Sets whether the sprite's pivot point should be relative to the trimmed bounds.
| extrude |sprite | [pixels],<br/>[wrap-mode] | Adds a padding around the sprite and fills it depending on the _wrap-mode_:<br/>- _clamp_ (default)<br/>- _mirror_:<br/>- _repeat_: .
| extrude |sprite | [pixels],<br/>[wrap-mode] | Adds a padding around the sprite and fills it depending on the _wrap-mode_:<br/>- _clamp_: Clamp to border pixels (default).<br/>- _mirror_: Mirror border pixels.<br/>- _repeat_: Repeat border pixels.
| common-divisor |sprite | x, [y] | Restricts the sprite's size to be divisible by a certain number of pixels. Smaller sprites are filled up with transparency.
| group |- | - | Can be used for opening a new scope, to limit for example the effect of a tag.

Expand Down
2 changes: 1 addition & 1 deletion src/Definition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ void apply_definition(Definition definition,
case Definition::pack: {
const auto string = check_string();
if (const auto index = index_of(string,
{ "binpack", "compact", "single", "keep" }); index >= 0)
{ "binpack", "rows", "columns", "compact", "single", "keep" }); index >= 0)
state.pack = static_cast<Pack>(index);
else
error("invalid pack method '", string, "'");
Expand Down
2 changes: 1 addition & 1 deletion src/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ enum class Trim { none, rect, convex };

enum class Alpha { keep, clear, bleed, premultiply, colorkey };

enum class Pack { binpack, compact, single, keep };
enum class Pack { binpack, rows, columns, compact, single, keep };

enum class Duplicates { keep, share, drop };

Expand Down
81 changes: 81 additions & 0 deletions src/pack_lines.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@

#include "packing.h"

namespace spright {

void pack_lines(bool horizontal, const OutputPtr& output,
SpriteSpan sprites, std::vector<Texture>& textures) {

const auto add_texture = [&](SpriteSpan sprites) {
auto texture = Texture{ output,
static_cast<int>(textures.size()),
0, 0, sprites,
};
recompute_texture_size(texture);
textures.push_back(std::move(texture));
};

const auto max_width = (output->max_width ?
output->max_width- output->border_padding * 2 :
std::numeric_limits<int>::max());
const auto max_height = (output->max_height ?
output->max_height - output->border_padding * 2 :
std::numeric_limits<int>::max());
const auto max_textures = static_cast<size_t>(output->filename.count());

auto pos = Point{ };
auto size = Size{ };
auto line_size = 0;

// d = direction, p = perpendicular
auto& pos_d = (horizontal ? pos.x : pos.y);
auto& pos_p = (horizontal ? pos.y : pos.x);
const auto& size_d = (horizontal ? size.x : size.y);
const auto& size_p = (horizontal ? size.y : size.x);
const auto max_d = (horizontal ? max_width : max_height);
const auto max_p = (horizontal ? max_height : max_width);

auto first_sprite = sprites.begin();
auto it = first_sprite;
for (; it != sprites.end(); ++it) {
auto& sprite = *it;
size = get_sprite_size(sprite);
size.x += output->shape_padding;
size.y += output->shape_padding;

if (pos_d + size_d > max_d) {
pos_d = 0;
pos_p += line_size;
line_size = 0;
}
if (pos_p + size_p > max_p) {
add_texture({ first_sprite, it });
if (textures.size() >= max_textures)
break;
first_sprite = it;
pos.x = 0;
pos.y = 0;
line_size = 0;
}
if (pos.x + size.x > max_width ||
pos.y + size.y > max_height)
break;

const auto indent = get_sprite_indent(sprite);
sprite.trimmed_rect = {
pos.x + indent.x + output->border_padding,
pos.y + indent.y + output->border_padding,
sprite.trimmed_source_rect.w,
sprite.trimmed_source_rect.h
};

pos_d += size_d;
line_size = std::max(line_size, size_p);
}
if (it != sprites.end())
throw std::runtime_error("not all sprites could be packed");

add_texture({ first_sprite, it });
}

} // namespace
19 changes: 13 additions & 6 deletions src/packing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ namespace {
case Pack::compact: return pack_compact(output, sprites, textures);
case Pack::single: return pack_single(output, sprites, textures);
case Pack::keep: return pack_keep(output, sprites, textures);
case Pack::rows: return pack_lines(true, output, sprites, textures);
case Pack::columns: return pack_lines(false, output, sprites, textures);
}
}

Expand All @@ -100,19 +102,24 @@ namespace {
}
}

// when dropping duplicates, restore order of sprites before packing
if (output->duplicates == Duplicates::drop) {
std::sort(unique_sprites.begin(), unique_sprites.end(),
[](const Sprite& a, const Sprite& b) { return (a.index < b.index); });
for (auto i = unique_sprites.size(); i < sprites.size(); ++i)
sprites[i] = { };
}

pack_texture(output, unique_sprites, textures);

for (auto i = size_t{ }; i < duplicates.size(); ++i) {
auto& duplicate = sprites[sprites.size() - 1 - i];
if (output->duplicates == Duplicates::share) {
if (output->duplicates == Duplicates::share) {
for (auto i = size_t{ }; i < duplicates.size(); ++i) {
auto& duplicate = sprites[sprites.size() - 1 - i];
const auto& sprite = unique_sprites[duplicates[i]];
duplicate.texture_index = sprite.texture_index;
duplicate.trimmed_rect = sprite.trimmed_rect;
duplicate.rotated = sprite.rotated;
}
else {
duplicate = { };
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/packing.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ void pack_single(const OutputPtr& output, SpriteSpan sprites,
std::vector<Texture>& textures);
void pack_keep(const OutputPtr& output, SpriteSpan sprites,
std::vector<Texture>& textures);
void pack_lines(bool horizontal, const OutputPtr& output,
SpriteSpan sprites, std::vector<Texture>& textures);

void recompute_texture_size(Texture& texture);

Expand Down

0 comments on commit 917a396

Please sign in to comment.