Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Implement maxrects packer #10

Merged
merged 14 commits into from
Jul 13, 2019
12 changes: 10 additions & 2 deletions sheep/examples/simple_pack/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,19 @@ fn main() {

// Do the actual packing! 4 defines the stride, since we're using rgba8 we
// have 4 bytes per pixel.
let sprite_sheet = sheep::pack::<SimplePacker>(sprites, 4);
let results = sheep::pack::<SimplePacker>(sprites, 4, Default::default());

// SimplePacker always returns a single result. Other packers can return
// multiple sheets; should they, for example, choose to enforce a maximum
// texture size per sheet.
let sprite_sheet = results
.into_iter()
.next()
.expect("Should have returned a spritesheet");

// Now, we can encode the sprite sheet in a format of our choosing to
// save things such as offsets, positions of the sprites and so on.
let meta = sheep::encode::<AmethystFormat>(&sprite_sheet);
let meta = sheep::encode::<AmethystFormat>(&sprite_sheet, ());

// Next, we save the output to a file using the image crate again.
let outbuf = image::RgbaImage::from_vec(
Expand Down
65 changes: 40 additions & 25 deletions sheep/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#![feature(test)]
extern crate test;
happenslol marked this conversation as resolved.
Show resolved Hide resolved

#[cfg(feature = "amethyst")]
extern crate serde;

Expand All @@ -11,7 +14,11 @@ mod sprite;

pub use {
format::Format,
pack::{simple::SimplePacker, Packer, PackerResult},
pack::{
maxrects::{MaxrectsOptions, MaxrectsPacker},
simple::SimplePacker,
Packer, PackerResult,
},
sprite::{InputSprite, Sprite, SpriteAnchor, SpriteData},
};

Expand All @@ -21,15 +28,19 @@ pub use format::named::AmethystNamedFormat;

use sprite::{create_pixel_buffer, write_sprite};

#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct SpriteSheet {
pub bytes: Vec<u8>,
pub stride: usize,
pub dimensions: (u32, u32),
anchors: Vec<SpriteAnchor>,
}

pub fn pack<P: Packer>(input: Vec<InputSprite>, stride: usize) -> SpriteSheet {
pub fn pack<P: Packer>(
input: Vec<InputSprite>,
stride: usize,
options: P::Options,
) -> Vec<SpriteSheet> {
let sprites = input
.into_iter()
.enumerate()
Expand All @@ -41,29 +52,33 @@ pub fn pack<P: Packer>(input: Vec<InputSprite>, stride: usize) -> SpriteSheet {
.map(|it| it.data)
.collect::<Vec<SpriteData>>();

let packer_result = P::pack(&sprite_data);
let mut buffer = create_pixel_buffer(packer_result.dimensions, stride);
sprites.into_iter().for_each(|sprite| {
let anchor = packer_result
.anchors
.iter()
.find(|it| it.id == sprite.data.id)
.expect("Should have found anchor for sprite");
write_sprite(
&mut buffer,
packer_result.dimensions,
stride,
&sprite,
&anchor,
);
});
let packer_result = P::pack(&sprite_data, options);

packer_result
.into_iter()
.map(|sheet| {
let mut buffer = create_pixel_buffer(sheet.dimensions, stride);
sprites
.iter()
.filter_map(|sprite| {
sheet
.anchors
.iter()
.find(|anchor| anchor.id == sprite.data.id)
.map(|anchor| (sprite, anchor))
})
.for_each(|(sprite, anchor)| {
write_sprite(&mut buffer, sheet.dimensions, stride, &sprite, &anchor);
});

SpriteSheet {
bytes: buffer,
stride: stride,
dimensions: packer_result.dimensions,
anchors: packer_result.anchors,
}
SpriteSheet {
bytes: buffer,
stride: stride,
dimensions: sheet.dimensions,
anchors: sheet.anchors,
}
})
.collect()
}

pub fn encode<F>(sprite_sheet: &SpriteSheet, options: F::Options) -> F::Data
Expand Down
Loading