From 88d0550ff0786372f83de47d613df6a04b4a4085 Mon Sep 17 00:00:00 2001 From: MrGVSV Date: Sat, 8 Jan 2022 15:17:50 -0800 Subject: [PATCH 1/5] Add support for Bevy 0.6 --- Cargo.toml | 20 ++++++++---- examples/atlas.rs | 19 ++++------- src/store.rs | 22 ++++++------- src/tile_atlas.rs | 83 +++++++++++++++++++++++++++++------------------ 4 files changed, 83 insertions(+), 61 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 23f662b..5dc7bda 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bevy_tile_atlas" version = "0.1.4" -edition = "2018" +edition = "2021" authors = ["Gino Valente "] description = "A TextureAtlas builder for ordered tilesets" repository = "https://github.com/MrGVSV/bevy_tile_atlas" @@ -10,14 +10,22 @@ keywords = ["bevy", "tile", "tileset", "texture", "ordered"] readme = "README.md" exclude = ["assets/**/*", ".github/**/*"] -[badges] -maintenance = { status = "as-is" } - - [dependencies] -bevy = "0.5" +bevy_asset = { version = "0.6", default-features = false } +bevy_ecs = { version = "0.6", default-features = false } +bevy_log = { version = "0.6", default-features = false, optional = true } +bevy_math = { version = "0.6", default-features = false } +bevy_render = { version = "0.6", default-features = false } +bevy_sprite = { version = "0.6", default-features = false } thiserror = "1.0.30" +[dev-dependencies] +bevy = "0.6" + +[features] +default = ["debug"] +debug = [] + [[example]] name = "atlas" path = "examples/atlas.rs" diff --git a/examples/atlas.rs b/examples/atlas.rs index 5c0b675..752b865 100644 --- a/examples/atlas.rs +++ b/examples/atlas.rs @@ -15,18 +15,14 @@ use bevy::prelude::*; use bevy_tile_atlas::TileAtlasBuilder; fn main() { - App::build() + App::new() .add_plugins(DefaultPlugins) .init_resource::() .init_resource::() .add_state(AppState::LoadTileset) - .add_system_set(SystemSet::on_enter(AppState::LoadTileset).with_system(load_tiles.system())) - .add_system_set( - SystemSet::on_update(AppState::CreateTileset).with_system(create_atlas.system()), - ) - .add_system_set( - SystemSet::on_enter(AppState::DisplayTileset).with_system(display_atlas.system()), - ) + .add_system_set(SystemSet::on_enter(AppState::LoadTileset).with_system(load_tiles)) + .add_system_set(SystemSet::on_update(AppState::CreateTileset).with_system(create_atlas)) + .add_system_set(SystemSet::on_enter(AppState::DisplayTileset).with_system(display_atlas)) .run(); } @@ -63,7 +59,7 @@ fn load_tiles( fn create_atlas( mut atlas: ResMut, - mut textures: ResMut>, + mut textures: ResMut>, mut state: ResMut>, handles: Res, asset_server: Res, @@ -79,7 +75,7 @@ fn create_atlas( for handle in &handles.0 { if let Some(texture) = textures.get(handle) { - if let Ok(index) = builder.add_texture(handle.clone().typed::(), texture) { + if let Ok(index) = builder.add_texture(handle.clone().typed::(), texture) { println!("Added texture at index: {}", index); } } @@ -100,7 +96,6 @@ fn create_atlas( fn display_atlas( mut atlas_res: ResMut, mut commands: Commands, - mut materials: ResMut>, mut atlases: ResMut>, ) { commands.spawn_bundle(OrthographicCameraBundle::new_2d()); @@ -122,7 +117,7 @@ fn display_atlas( // Display the whole tileset commands.spawn_bundle(SpriteBundle { - material: materials.add(handle.into()), + texture: handle, ..Default::default() }); diff --git a/src/store.rs b/src/store.rs index 2dcce42..31dfcea 100644 --- a/src/store.rs +++ b/src/store.rs @@ -1,29 +1,29 @@ -use bevy::asset::{Assets, Handle, HandleId}; -use bevy::ecs::component::Component; -use bevy::prelude::{ResMut, Texture}; +use bevy_asset::{Assets, Handle, HandleId}; +use bevy_ecs::system::{ResMut, Resource}; +use bevy_render::texture::Image; use std::ops::{Deref, DerefMut}; pub trait TextureStore { - fn add(&mut self, asset: Texture) -> Handle; - fn get>(&self, handle: H) -> Option<&Texture>; + fn add(&mut self, asset: Image) -> Handle; + fn get>(&self, handle: H) -> Option<&Image>; } -impl TextureStore for Assets { - fn add(&mut self, asset: Texture) -> Handle { +impl TextureStore for Assets { + fn add(&mut self, asset: Image) -> Handle { self.add(asset) } - fn get>(&self, handle: H) -> Option<&Texture> { + fn get>(&self, handle: H) -> Option<&Image> { self.get(handle) } } -impl<'w, T: TextureStore + Component> TextureStore for ResMut<'w, T> { - fn add(&mut self, asset: Texture) -> Handle { +impl<'w, T: TextureStore + Resource> TextureStore for ResMut<'w, T> { + fn add(&mut self, asset: Image) -> Handle { self.deref_mut().add(asset) } - fn get>(&self, handle: H) -> Option<&Texture> { + fn get>(&self, handle: H) -> Option<&Image> { self.deref().get(handle) } } diff --git a/src/tile_atlas.rs b/src/tile_atlas.rs index 3242877..69135ea 100644 --- a/src/tile_atlas.rs +++ b/src/tile_atlas.rs @@ -1,8 +1,9 @@ use crate::TextureStore; -use bevy::log::{debug, error, warn}; -use bevy::prelude::{Handle, Texture, TextureAtlas, Vec2}; -use bevy::render::texture::{Extent3d, TextureDimension, TextureFormat}; -use bevy::sprite::{Rect, TextureAtlasBuilderError}; +use bevy_asset::Handle; +use bevy_math::Vec2; +use bevy_render::render_resource::{Extent3d, TextureDimension, TextureFormat}; +use bevy_render::texture::{Image, TextureFormatPixelInfo}; +use bevy_sprite::{Rect, TextureAtlas, TextureAtlasBuilderError}; use std::collections::HashMap; use thiserror::Error; @@ -28,7 +29,7 @@ pub struct TileAtlasBuilder { /// If `None`, then no wrapping (i.e. single row) max_columns: Option, /// The ordered collection of texture handles in this atlas - handles: Vec>, + handles: Vec>, /// The texture format for the textures that will be loaded in the atlas. format: TextureFormat, /// Enable automatic format conversion for textures if they are not in the atlas format. @@ -152,21 +153,30 @@ impl TileAtlasBuilder { /// pub fn add_texture( &mut self, - texture_handle: Handle, - texture: &Texture, + texture_handle: Handle, + texture: &Image, ) -> Result { if let Some(size) = self.tile_size { - if texture.size.width > size.x as u32 || texture.size.height > size.y as u32 { + if texture.texture_descriptor.size.width > size.x as u32 + || texture.texture_descriptor.size.height > size.y as u32 + { let expected = size; - let found = texture.size.as_vec3().truncate(); - warn!( + let found = Vec2::new( + texture.texture_descriptor.size.width as f32, + texture.texture_descriptor.size.height as f32, + ); + #[cfg(feature = "debug")] + bevy_log::warn!( "The given texture does not fit into specified tile size (expected: {:?}, found: {:?}). Skipping...", expected, found, ); return Err(TileAtlasBuilderError::InvalidTileSize { expected, found }); } } else { - let new_size = texture.size.as_vec3().truncate(); + let new_size = Vec2::new( + texture.texture_descriptor.size.width as f32, + texture.texture_descriptor.size.height as f32, + ); self.tile_size = Some(new_size); }; @@ -188,12 +198,12 @@ impl TileAtlasBuilder { let total_rows = ((total as f32) / self.get_max_columns() as f32).ceil() as usize; - let mut atlas_texture = Texture::new_fill( - Extent3d::new( - (self.get_max_columns() as f32 * tile_size.x) as u32, - ((total_rows as f32) * tile_size.y) as u32, - 1, - ), + let mut atlas_texture = Image::new_fill( + Extent3d { + width: (self.get_max_columns() as f32 * tile_size.x) as u32, + height: ((total_rows as f32) * tile_size.y) as u32, + depth_or_array_layers: 1, + }, TextureDimension::D2, &[0, 0, 0, 0], self.format, @@ -212,10 +222,12 @@ impl TileAtlasBuilder { texture_handles.insert(handle.clone_weak(), index); texture_rects.push(Rect { min, max }); - if texture.format != self.format && !self.auto_format_conversion { - warn!( + if texture.texture_descriptor.format != self.format && !self.auto_format_conversion { + #[cfg(feature = "debug")] + bevy_log::warn!( "Loading a texture of format '{:?}' in an atlas with format '{:?}'", - texture.format, self.format + texture.texture_descriptor.format, + self.format ); return Err(TileAtlasBuilderError::Internal( TextureAtlasBuilderError::WrongFormat, @@ -232,7 +244,10 @@ impl TileAtlasBuilder { } Ok(TextureAtlas { - size: atlas_texture.size.as_vec3().truncate(), + size: Vec2::new( + atlas_texture.texture_descriptor.size.width as f32, + atlas_texture.texture_descriptor.size.height as f32, + ), texture: textures.add(atlas_texture), textures: texture_rects, texture_handles: Some(texture_handles), @@ -241,31 +256,35 @@ impl TileAtlasBuilder { fn copy_converted_texture( &self, - atlas_texture: &mut Texture, - texture: &Texture, + atlas_texture: &mut Image, + texture: &Image, column_index: usize, row_index: usize, ) { - if self.format == texture.format { + if self.format == texture.texture_descriptor.format { self.copy_texture_to_atlas(atlas_texture, texture, column_index, row_index); } else if let Some(converted_texture) = texture.convert(self.format) { - debug!( + #[cfg(feature = "debug")] + bevy_log::debug!( "Converting texture from '{:?}' to '{:?}'", - texture.format, self.format + texture.texture_descriptor.format, + self.format ); self.copy_texture_to_atlas(atlas_texture, &converted_texture, column_index, row_index); } else { - error!( + #[cfg(feature = "debug")] + bevy_log::error!( "Error converting texture from '{:?}' to '{:?}', ignoring", - texture.format, self.format + texture.texture_descriptor.format, + self.format ); } } fn copy_texture_to_atlas( &self, - atlas_texture: &mut Texture, - texture: &Texture, + atlas_texture: &mut Image, + texture: &Image, column_index: usize, row_index: usize, ) { @@ -276,8 +295,8 @@ impl TileAtlasBuilder { let rect_height = tile_size.y as usize; let rect_x = column_index * tile_size.x as usize; let rect_y = row_index * tile_size.y as usize; - let atlas_width = atlas_texture.size.width as usize; - let format_size = atlas_texture.format.pixel_size(); + let atlas_width = atlas_texture.texture_descriptor.size.width as usize; + let format_size = atlas_texture.texture_descriptor.format.pixel_size(); for (texture_y, bound_y) in (rect_y..rect_y + rect_height).enumerate() { let begin = (bound_y * atlas_width + rect_x) * format_size; From 995eb0293b4134badc0a542a84a74f0db7161458 Mon Sep 17 00:00:00 2001 From: MrGVSV Date: Sat, 8 Jan 2022 15:30:27 -0800 Subject: [PATCH 2/5] Bump version 0.1.4 -> 0.2.0 --- Cargo.toml | 2 +- README.md | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5dc7bda..b05e4ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bevy_tile_atlas" -version = "0.1.4" +version = "0.2.0" edition = "2021" authors = ["Gino Valente "] description = "A TextureAtlas builder for ordered tilesets" diff --git a/README.md b/README.md index 32f3ca9..30dc747 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ This crate is essentially an augmentation of Bevy's own `TextureAtlasBuilder`. Add to your `[dependencies]` list in `Cargo.toml`: ```toml -bevy_tile_atlas = "0.1.4" +bevy_tile_atlas = "0.2.0" ``` ## Usage @@ -40,7 +40,7 @@ use bevy_tile_atlas::TileAtlasBuilder; /// Creates a tile-based, ordered `TextureAtlas` /// /// Assumes that the given handles are all loaded and in their desired order -fn build_tileset(handles: Vec>, textures: &mut Assets) -> TextureAtlas { +fn build_tileset(handles: Vec>, textures: &mut Assets) -> TextureAtlas { let mut builder = TileAtlasBuilder::default(); for handle in handles { @@ -54,6 +54,13 @@ fn build_tileset(handles: Vec>, textures: &mut Assets) > **Note:** Duplicate textures can be added. This is helpful for when tiles need to be at multiple indices at once. +## Bevy Compatibility + +| bevy | bevy_tile_atlas | +| ---- | --------------- | +| 0.6 | 0.2.0 | +| 0.5 | 0.1.4 | + ## FAQ **If this was made for `bevy_ecs_tilemap`, why did you not submit it as a PR?** @@ -66,4 +73,4 @@ I didn't have to enforce the tile restriction, but I didn't see this being used **Is the order guaranteed for whole folders of textures?** -If you load from a whole folder, the order of insertion will depend on how Bevy chooses to load the files (which I think can vary, though I'm not sure). Therefore, it's recommended to either manually place the tile handles into a `Vec` or array, or use some other mechanism to automatically order them (i.e. a config file). \ No newline at end of file +If you load from a whole folder, the order of insertion will depend on how Bevy chooses to load the files (which I think can vary, though I'm not sure). Therefore, it's recommended to either manually place the tile handles into a `Vec` or array, or use some other mechanism to automatically order them (i.e. a [config file).](https://github.com/MrGVSV/bevy_tileset) \ No newline at end of file From 643ff5cb84d4c69326a6d9e1b46732f9202d9ab7 Mon Sep 17 00:00:00 2001 From: MrGVSV Date: Sat, 8 Jan 2022 15:36:22 -0800 Subject: [PATCH 3/5] Updated "debug" feature --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b05e4ec..5215774 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ bevy = "0.6" [features] default = ["debug"] -debug = [] +debug = ["bevy_log"] [[example]] name = "atlas" From 92a1807a337d3052d2b04c67d93d063f48257698 Mon Sep 17 00:00:00 2001 From: MrGVSV Date: Sat, 8 Jan 2022 15:52:12 -0800 Subject: [PATCH 4/5] Updated documentation --- src/lib.rs | 28 ++++++++++++++++++++++++++++ src/store.rs | 9 +++++++++ src/tile_atlas.rs | 2 ++ 3 files changed, 39 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 95787d2..48079d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,31 @@ +//! bevy_tile_atlas is a `TextureAtlas` builder for ordered tilesets. +//! +//! In other words, this crate is used to generate a `TileAtlas` that respects the order of insertion, +//! allowing its sub-textures to exist at known indices. This is helpful for texture animations, where +//! the frames are designated by a range of indices to loop through. It can also be helpful for retrieving +//! a sub-texture without needing access to its handle (i.e., "get texture at index at index 7" instead of +//! storing/passing around a `Handle`). +//! +//! ## Example +//! ``` +//! # use bevy::prelude::*; +//! # use bevy_tile_atlas::TileAtlasBuilder; +//! +//! /// Creates a tile-based, ordered `TextureAtlas` +//! /// +//! /// Assumes that the given handles are all loaded and in their desired order +//! fn build_tileset(handles: Vec>, textures: &mut Assets) -> TextureAtlas { +//! let mut builder = TileAtlasBuilder::default(); +//! +//! for handle in handles { +//! let texture = textures.get(&handle).unwrap(); +//! builder.add_texture(handle, texture); +//! } +//! +//! builder.finish(textures).unwrap() +//! } +//! ``` + mod store; mod tile_atlas; diff --git a/src/store.rs b/src/store.rs index 31dfcea..dc66dd2 100644 --- a/src/store.rs +++ b/src/store.rs @@ -1,10 +1,19 @@ +//! Defines the `TextureStore` trait which is used by `TileAtlasBuilder` to manage its textures + use bevy_asset::{Assets, Handle, HandleId}; use bevy_ecs::system::{ResMut, Resource}; use bevy_render::texture::Image; use std::ops::{Deref, DerefMut}; +/// Trait used in the [`TileAtlasBuilder::finish`](crate::TileAtlasBuilder::finish) method to get and +/// add textures. +/// +/// The reason for such a trait and not simply using `Assets` is to allow the builder to be used +/// in places where `Assets` might not be available (such as within a custom `AssetLoader`). pub trait TextureStore { + /// Add a texture to the store fn add(&mut self, asset: Image) -> Handle; + /// Get a texture from the store fn get>(&self, handle: H) -> Option<&Image>; } diff --git a/src/tile_atlas.rs b/src/tile_atlas.rs index 69135ea..f40501c 100644 --- a/src/tile_atlas.rs +++ b/src/tile_atlas.rs @@ -1,3 +1,5 @@ +//! Contains the atlas builder and its associated structs + use crate::TextureStore; use bevy_asset::Handle; use bevy_math::Vec2; From b5580cf8281da265b42d3d9633310f611f21aa94 Mon Sep 17 00:00:00 2001 From: MrGVSV Date: Sat, 8 Jan 2022 15:53:58 -0800 Subject: [PATCH 5/5] Added doc to feature --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 5215774..6bae590 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ bevy = "0.6" [features] default = ["debug"] +# Enables logging (specifically for warnings, errors, or automatic texture format conversions) debug = ["bevy_log"] [[example]]