From a2cf90e5b5b00d3c9572208f66217eaac50f60ae Mon Sep 17 00:00:00 2001 From: James Bell Date: Fri, 19 Apr 2024 20:52:55 -0400 Subject: [PATCH 1/4] Split 2d and 3d --- Cargo.toml | 2 +- crates/bevy_tiles/examples/basic_2d.rs | 21 +- crates/bevy_tiles/examples/basic_3d.rs | 22 +- crates/bevy_tiles/examples/logo.rs | 8 +- crates/bevy_tiles/examples/spatial.rs | 14 +- crates/bevy_tiles/src/chunks.rs | 33 +- crates/bevy_tiles/src/chunks/chunk_query.rs | 32 +- crates/bevy_tiles/src/commands.rs | 301 +++++++++--------- crates/bevy_tiles/src/commands/chunk_batch.rs | 16 +- .../bevy_tiles/src/commands/chunk_single.rs | 4 +- crates/bevy_tiles/src/commands/tile_batch.rs | 34 +- crates/bevy_tiles/src/commands/tile_single.rs | 12 +- crates/bevy_tiles/src/coords.rs | 69 ++-- crates/bevy_tiles/src/lib.rs | 59 +++- crates/bevy_tiles/src/maps.rs | 2 +- crates/bevy_tiles/src/tiles.rs | 38 ++- crates/bevy_tiles/src/tiles/tile_query.rs | 116 +++---- 17 files changed, 422 insertions(+), 361 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 65664c0..9e83a76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,4 +33,4 @@ undocumented_unsafe_blocks = "deny" all = "deny" [workspace.lints.rust] -unused_imports = "warn" \ No newline at end of file +unused_imports = "warn" diff --git a/crates/bevy_tiles/examples/basic_2d.rs b/crates/bevy_tiles/examples/basic_2d.rs index 3868019..7a5923b 100644 --- a/crates/bevy_tiles/examples/basic_2d.rs +++ b/crates/bevy_tiles/examples/basic_2d.rs @@ -1,5 +1,5 @@ use bevy::{prelude::*, sprite::SpriteBundle, DefaultPlugins}; -use bevy_tiles::prelude::*; +use bevy_tiles::{commands::TileCommandExt, coords::CoordIterator, tiles_2d::*, TilesPlugin}; fn main() { App::new() @@ -25,7 +25,7 @@ fn spawn(mut commands: Commands, asset_server: Res) { let character = asset_server.load("character.png"); commands.spawn(Camera2dBundle::default()); - let mut map = commands.spawn_map::<2>(16, GameLayer); + let mut map = commands.spawn_map(16, GameLayer); let sprite_bundle = SpriteBundle { texture: block, @@ -64,23 +64,22 @@ fn move_character( let map_id = map.single(); let walls = walls_maps.get_map(map_id).unwrap(); - let x = keyboard_input.just_pressed(KeyCode::KeyD) as isize - - keyboard_input.just_pressed(KeyCode::KeyA) as isize; + let x = keyboard_input.just_pressed(KeyCode::KeyD) as i32 + - keyboard_input.just_pressed(KeyCode::KeyA) as i32; - let y = keyboard_input.just_pressed(KeyCode::KeyW) as isize - - keyboard_input.just_pressed(KeyCode::KeyS) as isize; + let y = keyboard_input.just_pressed(KeyCode::KeyW) as i32 + - keyboard_input.just_pressed(KeyCode::KeyS) as i32; - let char_c = character.get_single().unwrap(); - let new_coord = [char_c[0] + x, char_c[1] + y]; + let char_c = IVec2::from(*character.get_single().unwrap()); + let new_coord = char_c + IVec2::new(x, y); if (x != 0 || y != 0) && walls.get_at(new_coord).is_none() { - commands.move_tile(map_id, **char_c, new_coord); + commands.move_tile(map_id, char_c, new_coord); } } fn sync_tile_transforms(mut tiles: Query<(&TileCoord, &mut Transform), Changed>) { for (tile_c, mut transform) in tiles.iter_mut() { - transform.translation.x = tile_c[0] as f32 * 16.0; - transform.translation.y = tile_c[1] as f32 * 16.0; + transform.translation = Vec3::from((Vec2::from(*tile_c) * Vec2::ONE * 16.0, 0.0)); } } diff --git a/crates/bevy_tiles/examples/basic_3d.rs b/crates/bevy_tiles/examples/basic_3d.rs index 2514133..b2dd6ee 100644 --- a/crates/bevy_tiles/examples/basic_3d.rs +++ b/crates/bevy_tiles/examples/basic_3d.rs @@ -1,7 +1,7 @@ use std::f32::consts::PI; use bevy::{pbr::CascadeShadowConfigBuilder, prelude::*, DefaultPlugins}; -use bevy_tiles::prelude::*; +use bevy_tiles::{commands::TileCommandExt, coords::CoordIterator, tiles_3d::*, TilesPlugin}; fn main() { App::new() @@ -56,7 +56,7 @@ fn spawn( ..Default::default() }; - let mut tile_commands = commands.spawn_map::<3>(16, GameLayer); + let mut tile_commands = commands.spawn_map(16, GameLayer); // spawn a 10 * 10 room tile_commands.spawn_tile_batch( @@ -108,20 +108,20 @@ fn move_character( keyboard_input: Res>, mut commands: Commands, map: Query>, - character: Query<&TileCoord<3>, With>, - walls_maps: TileMapQuery<(), With, 3>, + character: Query<&TileCoord, With>, + walls_maps: TileMapQuery<(), With>, ) { let map_id = map.single(); let walls = walls_maps.get_map(map_id).unwrap(); - let x = keyboard_input.just_pressed(KeyCode::KeyD) as isize - - keyboard_input.just_pressed(KeyCode::KeyA) as isize; + let x = keyboard_input.just_pressed(KeyCode::KeyD) as i32 + - keyboard_input.just_pressed(KeyCode::KeyA) as i32; - let y = keyboard_input.just_pressed(KeyCode::ShiftLeft) as isize - - keyboard_input.just_pressed(KeyCode::ControlLeft) as isize; + let y = keyboard_input.just_pressed(KeyCode::ShiftLeft) as i32 + - keyboard_input.just_pressed(KeyCode::ControlLeft) as i32; - let z = keyboard_input.just_pressed(KeyCode::KeyS) as isize - - keyboard_input.just_pressed(KeyCode::KeyW) as isize; + let z = keyboard_input.just_pressed(KeyCode::KeyS) as i32 + - keyboard_input.just_pressed(KeyCode::KeyW) as i32; let char_c = character.get_single().unwrap(); let new_coord = [char_c[0] + x, char_c[1] + y, char_c[2] + z]; @@ -131,7 +131,7 @@ fn move_character( } } -fn sync_tile_transforms(mut tiles: Query<(&TileCoord<3>, &mut Transform), Changed>>) { +fn sync_tile_transforms(mut tiles: Query<(&TileCoord, &mut Transform), Changed>) { for (tile_c, mut transform) in tiles.iter_mut() { transform.translation.x = tile_c[0] as f32; transform.translation.y = tile_c[1] as f32; diff --git a/crates/bevy_tiles/examples/logo.rs b/crates/bevy_tiles/examples/logo.rs index b6eaf08..53f41ec 100644 --- a/crates/bevy_tiles/examples/logo.rs +++ b/crates/bevy_tiles/examples/logo.rs @@ -1,5 +1,5 @@ use bevy::{prelude::*, sprite::SpriteBundle, DefaultPlugins}; -use bevy_tiles::prelude::*; +use bevy_tiles::{commands::TileCommandExt, tiles_2d::*, TilesPlugin}; fn main() { App::new() @@ -22,7 +22,7 @@ fn spawn(mut commands: Commands, asset_server: Res) { transform: Transform::from_translation(Vec3::new(480.0, 32.0, 0.0)), ..Default::default() }); - let mut map = commands.spawn_map::<2>(16, GameLayer); + let mut map = commands.spawn_map(16, GameLayer); let sprite_bundle = SpriteBundle { texture: block, @@ -39,7 +39,7 @@ eeeee eeee e e e e eeee8 eeeee e eeee eeeee let logo = logo.split('\n').enumerate().flat_map(|(y, line)| { line.bytes().enumerate().filter_map(move |(x, byte)| { if byte == 56 || byte == 101 { - Some([x as isize, 6 - y as isize]) + Some([x as i32, 6 - y as i32]) } else { None } @@ -47,7 +47,7 @@ eeeee eeee e e e e eeee8 eeeee e eeee eeeee }); // spawn a 10 * 10 room - map.spawn_tile_batch(logo.collect::>(), move |_| { + map.spawn_tile_batch(logo.collect::>(), move |_| { (Block, sprite_bundle.clone()) }); } diff --git a/crates/bevy_tiles/examples/spatial.rs b/crates/bevy_tiles/examples/spatial.rs index e13771d..342dfb1 100644 --- a/crates/bevy_tiles/examples/spatial.rs +++ b/crates/bevy_tiles/examples/spatial.rs @@ -6,7 +6,13 @@ use bevy::{ window::PrimaryWindow, DefaultPlugins, }; -use bevy_tiles::prelude::*; +use bevy_tiles::{ + commands::TileCommandExt, + coords::{calculate_chunk_coordinate, world_to_tile, CoordIterator}, + maps::TileMap, + tiles_2d::*, + TilesPlugin, +}; use std::ops::{Deref, DerefMut}; fn main() { @@ -54,7 +60,7 @@ fn spawn(mut commands: Commands, asset_server: Res) { }, ..Default::default() }); - let mut tile_commands = commands.spawn_map::<2>(32, GameLayer); + let mut tile_commands = commands.spawn_map(32, GameLayer); let sprite_bundle = SpriteBundle { texture: block, @@ -86,7 +92,7 @@ fn add_damage( .cursor_position() .and_then(|cursor| cam.viewport_to_world(cam_t, cursor.xy())) .map(|ray| ray.origin.truncate()) - .map(|pos| world_to_tile(pos.into(), 16.0)); + .map(|pos| world_to_tile(pos, 16.0)); if let Some(damage_pos) = buttons .just_pressed(MouseButton::Left) @@ -109,7 +115,7 @@ fn add_damage( .flatten() { let chunk_c = calculate_chunk_coordinate(damage_pos, map.get_chunk_size()); - commands.tile_map::<2>(map_id).despawn_chunk(chunk_c); + commands.tile_map(map_id).despawn_chunk(chunk_c); } } diff --git a/crates/bevy_tiles/src/chunks.rs b/crates/bevy_tiles/src/chunks.rs index 43e025d..1d1a35d 100644 --- a/crates/bevy_tiles/src/chunks.rs +++ b/crates/bevy_tiles/src/chunks.rs @@ -1,5 +1,6 @@ use bevy::{ ecs::{component::Component, entity::Entity}, + math::{IVec2, IVec3}, prelude::Deref, }; @@ -8,19 +9,35 @@ mod chunk_query; pub use chunk_query::*; /// An relation on chunks that point towards the map they are a part of. -#[derive(Component, Deref, Debug)] +/// # Note: +/// It probably won't break anything to manually copy this +/// to put it on your own entities, but this is only accurate +/// when mutated by the plugin. +#[derive(Component, Clone, Copy, Deref, Debug)] pub struct InMap(pub(crate) Entity); /// The coordinate of a given chunk. -/// # Note -#[derive(Component, Clone, Copy, Deref, Debug, PartialEq, Eq, Hash)] -pub struct ChunkCoord(pub(crate) [isize; N]); +/// # Note: +/// It probably won't break anything to manually copy this +/// to put it on your own entities, but this is only accurate +/// when mutated by the plugin. +#[derive(Component, Deref, Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct ChunkCoord(pub(crate) [i32; N]); + +impl From for ChunkCoord<2> { + fn from(value: IVec2) -> Self { + Self(value.into()) + } +} + +impl From for ChunkCoord<3> { + fn from(value: IVec3) -> Self { + Self(value.into()) + } +} /// Holds handles to all the tiles in a chunk. -/// # Note -/// Manually updating this value, adding it, or removing it from an entity may -/// cause issues, please only mutate chunk information via commands. -#[derive(Component, Deref, Debug)] +#[derive(Component, Debug)] pub struct Chunk(pub(crate) Vec>); impl Chunk { diff --git a/crates/bevy_tiles/src/chunks/chunk_query.rs b/crates/bevy_tiles/src/chunks/chunk_query.rs index f2d7ee7..3bb499e 100644 --- a/crates/bevy_tiles/src/chunks/chunk_query.rs +++ b/crates/bevy_tiles/src/chunks/chunk_query.rs @@ -11,9 +11,9 @@ use bevy::{ }; use crate::{ - chunks::ChunkCoord, + chunks::{Chunk, ChunkCoord, InMap}, + coords::CoordIterator, maps::TileMap, - prelude::{Chunk, CoordIterator, InMap}, }; /// Used to query chunks from any tile map. @@ -81,8 +81,9 @@ where #[inline] pub fn get_at( &self, - chunk_c: [isize; N], + chunk_c: impl Into<[i32; N]>, ) -> Option<<::ReadOnly as WorldQuery>::Item<'_>> { + let chunk_c = chunk_c.into(); let chunk_id = self.map.get_from_chunk(ChunkCoord(chunk_c))?; self.chunk_q.get(chunk_id).ok() @@ -96,8 +97,9 @@ where #[inline] pub unsafe fn get_at_unchecked( &self, - chunk_c: [isize; N], + chunk_c: impl Into<[i32; N]>, ) -> Option<::Item<'_>> { + let chunk_c = chunk_c.into(); let chunk_id = self.map.get_from_chunk(ChunkCoord(chunk_c))?; self.chunk_q.get_unchecked(chunk_id).ok() @@ -110,9 +112,11 @@ where #[inline] pub fn iter_in( &self, - corner_1: [isize; N], - corner_2: [isize; N], + corner_1: impl Into<[i32; N]>, + corner_2: impl Into<[i32; N]>, ) -> ChunkQueryIter<'_, 'a, C, N> { + let corner_1 = corner_1.into(); + let corner_2 = corner_2.into(); ChunkQueryIter::new(self, corner_1, corner_2) } } @@ -127,7 +131,11 @@ where /// # Note /// Coordinates are for these calls are in chunk coordinates. #[inline] - pub fn get_at_mut(&mut self, chunk_c: [isize; N]) -> Option<::Item<'_>> { + pub fn get_at_mut( + &mut self, + chunk_c: impl Into<[i32; N]>, + ) -> Option<::Item<'_>> { + let chunk_c = chunk_c.into(); let chunk_id = self.map.get_from_chunk(ChunkCoord(chunk_c))?; self.chunk_q.get_mut(chunk_id).ok() @@ -140,9 +148,11 @@ where #[inline] pub fn iter_in_mut( &mut self, - corner_1: [isize; N], - corner_2: [isize; N], + corner_1: impl Into<[i32; N]>, + corner_2: impl Into<[i32; N]>, ) -> ChunkQueryIterMut<'_, 'a, C, N> { + let corner_1 = corner_1.into(); + let corner_2 = corner_2.into(); ChunkQueryIterMut::new(self, corner_1, corner_2) } } @@ -154,7 +164,7 @@ pub struct ChunkQueryIter<'i, 'a, C, const N: usize> { } impl<'i, 'a, C, const N: usize> ChunkQueryIter<'i, 'a, C, N> { - fn new(chunk_q: &'i ChunkQuery<'a, C, N>, corner_1: [isize; N], corner_2: [isize; N]) -> Self { + fn new(chunk_q: &'i ChunkQuery<'a, C, N>, corner_1: [i32; N], corner_2: [i32; N]) -> Self { Self { chunk_q, coord_iter: CoordIterator::new(corner_1, corner_2), @@ -191,7 +201,7 @@ pub struct ChunkQueryIterMut<'i, 'a, C, const N: usize> { } impl<'i, 'a, C, const N: usize> ChunkQueryIterMut<'i, 'a, C, N> { - fn new(chunk_q: &'i ChunkQuery<'a, C, N>, corner_1: [isize; N], corner_2: [isize; N]) -> Self { + fn new(chunk_q: &'i ChunkQuery<'a, C, N>, corner_1: [i32; N], corner_2: [i32; N]) -> Self { Self { chunk_q, coord_iter: CoordIterator::new(corner_1, corner_2), diff --git a/crates/bevy_tiles/src/commands.rs b/crates/bevy_tiles/src/commands.rs index d208acf..584efa3 100644 --- a/crates/bevy_tiles/src/commands.rs +++ b/crates/bevy_tiles/src/commands.rs @@ -1,9 +1,9 @@ use std::{cmp::Eq, hash::Hash}; use crate::{ - prelude::{ - calculate_chunk_coordinate, calculate_tile_index, Chunk, ChunkCoord, InMap, TileMap, - }, + chunks::{Chunk, ChunkCoord, InMap}, + coords::{calculate_chunk_coordinate, calculate_tile_index}, + maps::TileMap, tiles::{InChunk, TileCoord, TileIndex}, }; @@ -34,7 +34,12 @@ pub struct TileMapCommands<'a, 'w, 's, const N: usize> { impl<'a, 'w, 's, const N: usize> TileMapCommands<'a, 'w, 's, N> { /// Spawns a tile and returns a handle to the underlying entity. /// This will despawn any tile that already exists in this coordinate - pub fn spawn_tile(&mut self, tile_c: [isize; N], bundle: impl Bundle) -> EntityCommands<'_> { + pub fn spawn_tile( + &mut self, + tile_c: impl Into<[i32; N]>, + bundle: impl Bundle, + ) -> EntityCommands<'_> { + let tile_c = tile_c.into(); self.commands.spawn_tile(self.map_id, tile_c, bundle) } @@ -42,9 +47,9 @@ impl<'a, 'w, 's, const N: usize> TileMapCommands<'a, 'w, 's, N> { /// This will despawn any tile that already exists in this coordinate pub fn spawn_tile_batch(&mut self, tile_cs: IC, bundle_f: F) -> &mut Self where - F: Fn([isize; N]) -> B + Send + 'static, + F: Fn([i32; N]) -> B + Send + 'static, B: Bundle + Send + 'static, - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { self.commands .spawn_tile_batch(self.map_id, tile_cs, bundle_f); @@ -52,7 +57,8 @@ impl<'a, 'w, 's, const N: usize> TileMapCommands<'a, 'w, 's, N> { } /// Despawns a tile. - pub fn despawn_tile(&mut self, tile_c: [isize; N]) -> &mut Self { + pub fn despawn_tile(&mut self, tile_c: impl Into<[i32; N]>) -> &mut Self { + let tile_c = tile_c.into(); self.commands.despawn_tile(self.map_id, tile_c); self } @@ -60,14 +66,20 @@ impl<'a, 'w, 's, const N: usize> TileMapCommands<'a, 'w, 's, N> { /// Despawns tiles from the given iterator. pub fn despawn_tile_batch(&mut self, tile_cs: IC) -> &mut Self where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { self.commands.despawn_tile_batch(self.map_id, tile_cs); self } /// Moves a tile from one coordinate to another, overwriting and despawning any tile in the new coordinate. - pub fn move_tile(&mut self, old_c: [isize; N], new_c: [isize; N]) -> &mut Self { + pub fn move_tile( + &mut self, + old_c: impl Into<[i32; N]>, + new_c: impl Into<[i32; N]>, + ) -> &mut Self { + let old_c = old_c.into(); + let new_c = new_c.into(); self.commands.move_tile(self.map_id, old_c, new_c); self } @@ -76,14 +88,20 @@ impl<'a, 'w, 's, const N: usize> TileMapCommands<'a, 'w, 's, N> { /// any tile found in the second coordinate. pub fn move_tile_batch(&mut self, tile_cs: IC) -> &mut Self where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { self.commands.move_tile_batch(self.map_id, tile_cs); self } /// Swaps two tiles if both exist, or moves one tile if the other doesn't exist. - pub fn swap_tiles(&mut self, tile_c_1: [isize; N], tile_c_2: [isize; N]) -> &mut Self { + pub fn swap_tiles( + &mut self, + tile_c_1: impl Into<[i32; N]>, + tile_c_2: impl Into<[i32; N]>, + ) -> &mut Self { + let tile_c_1 = tile_c_1.into(); + let tile_c_2 = tile_c_2.into(); self.commands.swap_tiles(self.map_id, tile_c_1, tile_c_2); self } @@ -91,14 +109,19 @@ impl<'a, 'w, 's, const N: usize> TileMapCommands<'a, 'w, 's, N> { /// Swap tiles from the first coordinate and the second coordinate pub fn swap_tile_batch(&mut self, tile_cs: IC) -> &mut Self where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { self.commands.swap_tile_batch(self.map_id, tile_cs); self } /// Manually spawn a chunk entity, note that this will overwrite and despawn existing chunks at this location. - pub fn spawn_chunk(&mut self, chunk_c: [isize; N], bundle: impl Bundle) -> EntityCommands<'_> { + pub fn spawn_chunk( + &mut self, + chunk_c: impl Into<[i32; N]>, + bundle: impl Bundle, + ) -> EntityCommands<'_> { + let chunk_c = chunk_c.into(); self.commands.spawn_chunk(self.map_id, chunk_c, bundle) } @@ -106,9 +129,9 @@ impl<'a, 'w, 's, const N: usize> TileMapCommands<'a, 'w, 's, N> { /// This will despawn any chunks (and their tiles) that already exists in this coordinate pub fn spawn_chunk_batch_with(&mut self, chunk_cs: IC, bundle_f: F) -> &mut Self where - F: Fn([isize; N]) -> B + Send + 'static, + F: Fn([i32; N]) -> B + Send + 'static, B: Bundle + Send + 'static, - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { self.commands .spawn_chunk_batch_with(self.map_id, chunk_cs, bundle_f); @@ -116,7 +139,8 @@ impl<'a, 'w, 's, const N: usize> TileMapCommands<'a, 'w, 's, N> { } /// Recursively despawn a chunk and all it's tiles. - pub fn despawn_chunk(&mut self, chunk_c: [isize; N]) -> &mut Self { + pub fn despawn_chunk(&mut self, chunk_c: impl Into<[i32; N]>) -> &mut Self { + let chunk_c = chunk_c.into(); self.commands.despawn_chunk(self.map_id, chunk_c); self } @@ -124,7 +148,7 @@ impl<'a, 'w, 's, const N: usize> TileMapCommands<'a, 'w, 's, N> { /// Despawns chunks (and their tiles) from the given iterator. pub fn despawn_chunk_batch(&mut self, chunk_cs: IC) -> &mut Self where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { self.commands.despawn_chunk_batch(self.map_id, chunk_cs); self @@ -132,7 +156,7 @@ impl<'a, 'w, 's, const N: usize> TileMapCommands<'a, 'w, 's, N> { /// Recursively despawns a map and all it's chunks and tiles. pub fn despawn_map(self) { - self.commands.despawn_map::(self.map_id); + TileCommandExt::::despawn_map(self.commands, self.map_id); } /// Get the id of the map. @@ -148,108 +172,94 @@ impl<'a, 'w, 's, const N: usize> TileMapCommands<'a, 'w, 's, N> { } /// Helper method for creating map specific commands. -pub trait TileCommandExt<'w, 's> { +pub trait TileCommandExt<'w, 's, const N: usize> { /// Gets [TileMapCommands] to apply commands at the tile map level. - fn tile_map<'a, const N: usize>(&'a mut self, map_id: Entity) - -> TileMapCommands<'a, 'w, 's, N>; + fn tile_map<'a>(&'a mut self, map_id: Entity) -> TileMapCommands<'a, 'w, 's, N>; /// Spawns a tile and returns a handle to the underlying entity. /// This will despawn any tile that already exists in this coordinate - fn spawn_tile( + fn spawn_tile( &mut self, map_id: Entity, - tile_c: [isize; N], + tile_c: [i32; N], bundle: impl Bundle, ) -> EntityCommands<'_>; /// Spawns tiles from the given iterator using the given function. /// This will despawn any tile that already exists in this coordinate - fn spawn_tile_batch( - &mut self, - map_id: Entity, - tile_cs: IC, - bundle_f: F, - ) where - F: Fn([isize; N]) -> B + Send + 'static, + fn spawn_tile_batch(&mut self, map_id: Entity, tile_cs: IC, bundle_f: F) + where + F: Fn([i32; N]) -> B + Send + 'static, B: Bundle + Send + 'static, - IC: IntoIterator + Send + 'static; + IC: IntoIterator + Send + 'static; /// Despawns a tile. - fn despawn_tile(&mut self, map_id: Entity, tile_c: [isize; N]) -> &mut Self; + fn despawn_tile(&mut self, map_id: Entity, tile_c: [i32; N]) -> &mut Self; /// Despawns tiles from the given iterator. - fn despawn_tile_batch(&mut self, map_id: Entity, tile_cs: IC) + fn despawn_tile_batch(&mut self, map_id: Entity, tile_cs: IC) where - IC: IntoIterator + Send + 'static; + IC: IntoIterator + Send + 'static; /// Moves a tile from one coordinate to another, overwriting and despawning any tile in the new coordinate. - fn move_tile( + fn move_tile( &mut self, map_id: Entity, - old_c: [isize; N], - new_c: [isize; N], + old_c: impl Into<[i32; N]>, + new_c: impl Into<[i32; N]>, ) -> &mut Self; /// Move tiles from the first coordinate to the second coordinate, despawning /// any tile found in the second coordinate. - fn move_tile_batch(&mut self, map_id: Entity, tile_cs: IC) + fn move_tile_batch(&mut self, map_id: Entity, tile_cs: IC) where - IC: IntoIterator + Send + 'static; + IC: IntoIterator + Send + 'static; /// Swaps two tiles if both exist, or moves one tile if the other doesn't exist. - fn swap_tiles( - &mut self, - map_id: Entity, - tile_c_1: [isize; N], - tile_c_2: [isize; N], - ) -> &mut Self; + fn swap_tiles(&mut self, map_id: Entity, tile_c_1: [i32; N], tile_c_2: [i32; N]) -> &mut Self; /// Swap tiles from the first coordinate and the second coordinate - fn swap_tile_batch(&mut self, map_id: Entity, tile_cs: IC) + fn swap_tile_batch(&mut self, map_id: Entity, tile_cs: IC) where - IC: IntoIterator + Send + 'static; + IC: IntoIterator + Send + 'static; /// Manually spawn a chunk entity, note that this will overwrite and despawn existing chunks at this location. - fn spawn_chunk( + fn spawn_chunk( &mut self, map_id: Entity, - chunk_c: [isize; N], + chunk_c: [i32; N], bundle: impl Bundle, ) -> EntityCommands<'_>; /// Spawns chunks from the given iterator using the given function. /// This will despawn any chunks (and their tiles) that already exists in this coordinate - fn spawn_chunk_batch_with( - &mut self, - map_id: Entity, - chunk_cs: IC, - bundle_f: F, - ) where - F: Fn([isize; N]) -> B + Send + 'static, + fn spawn_chunk_batch_with(&mut self, map_id: Entity, chunk_cs: IC, bundle_f: F) + where + F: Fn([i32; N]) -> B + Send + 'static, B: Bundle + Send + 'static, - IC: IntoIterator + Send + 'static; + IC: IntoIterator + Send + 'static; /// Recursively despawn a chunk and all it's tiles. - fn despawn_chunk(&mut self, map_id: Entity, chunk_c: [isize; N]) -> &mut Self; + fn despawn_chunk(&mut self, map_id: Entity, chunk_c: [i32; N]) -> &mut Self; /// Despawns chunks (and their tiles) from the given iterator. - fn despawn_chunk_batch(&mut self, map_id: Entity, chunk_cs: IC) + fn despawn_chunk_batch(&mut self, map_id: Entity, chunk_cs: IC) where - IC: IntoIterator + Send + 'static; + IC: IntoIterator + Send + 'static; /// Spawn a new map. - fn spawn_map( + fn spawn_map( &mut self, chunk_size: usize, bundle: impl Bundle, ) -> TileMapCommands<'_, 'w, 's, N>; /// Recursively despawns a map and all it's chunks and tiles. - fn despawn_map(&mut self, map_id: Entity) -> &mut Self; + fn despawn_map(&mut self, map_id: Entity) -> &mut Self; } -impl<'w, 's> TileCommandExt<'w, 's> for Commands<'w, 's> { - fn tile_map(&mut self, map_id: Entity) -> TileMapCommands<'_, 'w, 's, N> { +impl<'w, 's, const N: usize> TileCommandExt<'w, 's, N> for Commands<'w, 's> { + fn tile_map(&mut self, map_id: Entity) -> TileMapCommands<'_, 'w, 's, N> { TileMapCommands { commands: self, map_id, @@ -258,10 +268,10 @@ impl<'w, 's> TileCommandExt<'w, 's> for Commands<'w, 's> { /// Spawns a tile and returns a handle to the underlying entity. /// This will despawn any tile that already exists in this coordinate - fn spawn_tile( + fn spawn_tile( &mut self, map_id: Entity, - tile_c: [isize; N], + tile_c: [i32; N], bundle: impl Bundle, ) -> EntityCommands<'_> { let tile_id = self.spawn(bundle).id(); @@ -275,15 +285,11 @@ impl<'w, 's> TileCommandExt<'w, 's> for Commands<'w, 's> { /// Spawns tiles from the given iterator using the given function. /// This will despawn any tile that already exists in this coordinate - fn spawn_tile_batch( - &mut self, - map_id: Entity, - tile_cs: IC, - bundle_f: F, - ) where - F: Fn([isize; N]) -> B + Send + 'static, + fn spawn_tile_batch(&mut self, map_id: Entity, tile_cs: IC, bundle_f: F) + where + F: Fn([i32; N]) -> B + Send + 'static, B: Bundle + Send + 'static, - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { self.add(SpawnTileBatch:: { map_id, @@ -293,26 +299,28 @@ impl<'w, 's> TileCommandExt<'w, 's> for Commands<'w, 's> { } /// Despawns a tile. - fn despawn_tile(&mut self, map_id: Entity, tile_c: [isize; N]) -> &mut Self { + fn despawn_tile(&mut self, map_id: Entity, tile_c: [i32; N]) -> &mut Self { self.add(DespawnTile:: { map_id, tile_c }); self } /// Despawns tiles from the given iterator. - fn despawn_tile_batch(&mut self, map_id: Entity, tile_cs: IC) + fn despawn_tile_batch(&mut self, map_id: Entity, tile_cs: IC) where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { self.add(DespawnTileBatch:: { map_id, tile_cs }); } /// Moves a tile from one coordinate to another, overwriting and despawning any tile in the new coordinate. - fn move_tile( + fn move_tile( &mut self, map_id: Entity, - old_c: [isize; N], - new_c: [isize; N], + old_c: impl Into<[i32; N]>, + new_c: impl Into<[i32; N]>, ) -> &mut Self { + let old_c = old_c.into(); + let new_c = new_c.into(); self.add(MoveTile:: { map_id, old_c, @@ -323,20 +331,15 @@ impl<'w, 's> TileCommandExt<'w, 's> for Commands<'w, 's> { /// Move tiles from the first coordinate to the second coordinate, despawning /// any tile found in the second coordinate. - fn move_tile_batch(&mut self, map_id: Entity, tile_cs: IC) + fn move_tile_batch(&mut self, map_id: Entity, tile_cs: IC) where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { self.add(MoveTileBatch:: { map_id, tile_cs }); } /// Swaps two tiles if both exist, or moves one tile if the other doesn't exist. - fn swap_tiles( - &mut self, - map_id: Entity, - tile_c_1: [isize; N], - tile_c_2: [isize; N], - ) -> &mut Self { + fn swap_tiles(&mut self, map_id: Entity, tile_c_1: [i32; N], tile_c_2: [i32; N]) -> &mut Self { self.add(SwapTile:: { map_id, tile_c_1, @@ -346,18 +349,18 @@ impl<'w, 's> TileCommandExt<'w, 's> for Commands<'w, 's> { } /// Swap tiles from the first coordinate and the second coordinate - fn swap_tile_batch(&mut self, map_id: Entity, tile_cs: IC) + fn swap_tile_batch(&mut self, map_id: Entity, tile_cs: IC) where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { self.add(SwapTileBatch:: { map_id, tile_cs }); } /// Manually spawn a chunk entity, note that this will overwrite and despawn existing chunks at this location. - fn spawn_chunk( + fn spawn_chunk( &mut self, map_id: Entity, - chunk_c: [isize; N], + chunk_c: [i32; N], bundle: impl Bundle, ) -> EntityCommands<'_> { let chunk_id = self.spawn(bundle).id(); @@ -371,15 +374,11 @@ impl<'w, 's> TileCommandExt<'w, 's> for Commands<'w, 's> { /// Spawns chunks from the given iterator using the given function. /// This will despawn any chunks (and their tiles) that already exists in this coordinate - fn spawn_chunk_batch_with( - &mut self, - map_id: Entity, - chunk_cs: IC, - bundle_f: F, - ) where - F: Fn([isize; N]) -> B + Send + 'static, + fn spawn_chunk_batch_with(&mut self, map_id: Entity, chunk_cs: IC, bundle_f: F) + where + F: Fn([i32; N]) -> B + Send + 'static, B: Bundle + Send + 'static, - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { self.add(SpawnChunkBatch:: { map_id, @@ -389,21 +388,21 @@ impl<'w, 's> TileCommandExt<'w, 's> for Commands<'w, 's> { } /// Recursively despawn a chunk and all it's tiles. - fn despawn_chunk(&mut self, map_id: Entity, chunk_c: [isize; N]) -> &mut Self { + fn despawn_chunk(&mut self, map_id: Entity, chunk_c: [i32; N]) -> &mut Self { self.add(DespawnChunk:: { map_id, chunk_c }); self } /// Despawns chunks (and their tiles) from the given iterator. - fn despawn_chunk_batch(&mut self, map_id: Entity, chunk_cs: IC) + fn despawn_chunk_batch(&mut self, map_id: Entity, chunk_cs: IC) where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { self.add(DespawnChunkBatch:: { map_id, chunk_cs }); } /// Spawn a new map. - fn spawn_map( + fn spawn_map( &mut self, chunk_size: usize, bundle: impl Bundle, @@ -417,7 +416,7 @@ impl<'w, 's> TileCommandExt<'w, 's> for Commands<'w, 's> { } /// Recursively despawns a map and all it's chunks and tiles. - fn despawn_map(&mut self, map_id: Entity) -> &mut Self { + fn despawn_map(&mut self, map_id: Entity) -> &mut Self { self.add(DespawnMap:: { map_id }); self } @@ -430,13 +429,13 @@ fn spawn_or_remove_chunk( world: &mut World, map: &mut TileMap, map_id: Entity, - chunk_c: [isize; N], + chunk_c: [i32; N], ) -> (Entity, Chunk) { if let Some(chunk_info) = remove_chunk::(world, map, chunk_c) { chunk_info } else { let chunk_c = ChunkCoord(chunk_c); - let chunk_id = world.spawn((chunk_c, InMap(map_id))).id(); + let chunk_id = world.spawn((ChunkCoord(chunk_c.0), InMap(map_id))).id(); map.get_chunks_mut().insert(chunk_c, chunk_id); (chunk_id, Chunk::new(map.get_chunk_size().pow(N as u32))) } @@ -447,7 +446,7 @@ fn spawn_or_remove_chunk( fn remove_chunk( world: &mut World, map: &mut TileMap, - chunk_c: [isize; N], + chunk_c: [i32; N], ) -> Option<(Entity, Chunk)> { map.get_chunks_mut() .get::>(&ChunkCoord(chunk_c)) @@ -469,7 +468,7 @@ pub fn insert_tile_into_map( world: &mut World, map: &mut TileMap, map_id: Entity, - tile_c: [isize; N], + tile_c: [i32; N], tile_id: Entity, ) { let chunk_size = map.get_chunk_size(); @@ -500,7 +499,7 @@ pub fn insert_tile_into_map( pub fn insert_tile( world: &mut World, map_id: Entity, - tile_c: [isize; N], + tile_c: [i32; N], tile_id: Entity, ) { // Take the map out and get the id to reinsert it @@ -514,7 +513,7 @@ pub fn insert_tile( pub fn take_tile_from_map( world: &mut World, map: &mut TileMap, - tile_c: [isize; N], + tile_c: [i32; N], ) -> Option { let chunk_size = map.get_chunk_size(); // Get the old chunk or return @@ -530,7 +529,7 @@ pub fn take_tile_from_map( .and_then(|tile| tile.take()) .and_then(|tile_id| world.get_entity_mut(tile_id)) { - tile_e.remove::<(TileIndex, TileCoord, InChunk)>(); + tile_e.remove::<(TileIndex, TileCoord<2>, InChunk)>(); let tile_id = tile_e.id(); Some(tile_id) } else { @@ -545,7 +544,7 @@ pub fn take_tile_from_map( pub fn take_tile( world: &mut World, map_id: Entity, - tile_c: [isize; N], + tile_c: [i32; N], ) -> Option { // Get the map or return let mut map = remove_map::(world, map_id)?; @@ -558,7 +557,7 @@ pub fn take_tile( pub fn insert_tile_batch( world: &mut World, map_id: Entity, - tiles: impl IntoIterator, + tiles: impl IntoIterator, ) { // Remove the map, or spawn an entity to hold the map, then create an empty map let mut map = remove_map::(world, map_id) @@ -603,8 +602,8 @@ pub fn insert_tile_batch( pub fn take_tile_batch( world: &mut World, map_id: Entity, - tiles: impl IntoIterator, -) -> Vec<([isize; N], Entity)> { + tiles: impl IntoIterator, +) -> Vec<([i32; N], Entity)> { // Remove the map, or return if it doesn't exist let Some(mut map) = remove_map::(world, map_id) else { return Vec::new(); @@ -628,10 +627,10 @@ pub fn take_tile_batch( ( chunk_id, chunk, - tiles.into_iter().collect::>(), + tiles.into_iter().collect::>(), ) }) - .collect::)>>(); + .collect::)>>(); let mut tile_ids = Vec::new(); for (chunk_id, mut chunk, tiles) in tiles_with_chunk { @@ -644,7 +643,7 @@ pub fn take_tile_batch( .and_then(|tile| tile.take()) .and_then(|tile_id| world.get_entity_mut(tile_id)) { - tile_e.remove::<(TileIndex, TileCoord, InChunk)>(); + tile_e.remove::<(TileIndex, TileCoord, InChunk)>(); let tile_id = tile_e.id(); tile_ids.push((tile_c, tile_id)); } @@ -661,7 +660,7 @@ pub fn take_tile_batch( pub fn insert_chunk( world: &mut World, map_id: Entity, - chunk_c: [isize; N], + chunk_c: [i32; N], chunk_id: Entity, ) { let mut map = remove_map::(world, map_id) @@ -677,7 +676,7 @@ pub fn insert_chunk( let chunk_c = ChunkCoord(chunk_c); world.get_entity_mut(chunk_id).unwrap().insert(( Chunk::new(chunk_size.pow(N as u32)), - chunk_c, + ChunkCoord(chunk_c.0), InMap(map_id), )); map.get_chunks_mut().insert(chunk_c, chunk_id); @@ -692,7 +691,7 @@ pub fn insert_chunk( pub fn take_chunk( world: &mut World, map_id: Entity, - chunk_c: [isize; N], + chunk_c: [i32; N], ) -> Option { // Get the map or return let mut map = remove_map::(world, map_id)?; @@ -703,7 +702,7 @@ pub fn take_chunk( .remove::>(&ChunkCoord(chunk_c)) .and_then(|chunk_id| world.get_entity_mut(chunk_id)) { - let (chunk, _, _) = chunk_e.take::<(Chunk, ChunkCoord, InMap)>().unwrap(); + let (chunk, _, _) = chunk_e.take::<(Chunk, ChunkCoord<2>, InMap)>().unwrap(); let chunk_id = chunk_e.id(); for tile_id in chunk.0.into_iter().flatten() { if let Some(mut tile) = world.get_entity_mut(tile_id) { @@ -724,7 +723,7 @@ pub fn take_chunk( pub fn take_chunk_despawn_tiles( world: &mut World, map_id: Entity, - chunk_c: [isize; N], + chunk_c: [i32; N], ) -> Option { // Get the map or return let mut map = remove_map::(world, map_id)?; @@ -739,32 +738,35 @@ pub fn take_chunk_despawn_tiles( pub(crate) fn take_chunk_despawn_tiles_inner( world: &mut World, map: &mut TileMap, - chunk_c: [isize; N], + chunk_c: [i32; N], ) -> Option { // Get the old chunk or return let chunk_c = ChunkCoord(chunk_c); - let chunk_id = if let Some(mut chunk_e) = map - .get_chunks_mut() - .remove::>(&chunk_c) - .and_then(|chunk_id| world.get_entity_mut(chunk_id)) - { - let (chunk, _, _) = chunk_e.take::<(Chunk, ChunkCoord, InMap)>().unwrap(); - let chunk_id = chunk_e.id(); - for tile_id in chunk.0.into_iter().flatten() { - world.despawn(tile_id); - } - Some(chunk_id) + if let Some(chunk_id) = map.get_chunks_mut().remove::>(&chunk_c) { + despawn_chunk_tiles::(world, chunk_id) } else { None - }; - chunk_id + } +} + +pub(crate) fn despawn_chunk_tiles( + world: &mut World, + chunk_id: Entity, +) -> Option { + let mut chunk_e = world.get_entity_mut(chunk_id)?; + let (chunk, _, _) = chunk_e.take::<(Chunk, ChunkCoord, InMap)>().unwrap(); + let chunk_id = chunk_e.id(); + for tile_id in chunk.0.into_iter().flatten() { + world.despawn(tile_id); + } + Some(chunk_id) } /// Inserts a list of entities into map and treats them as chunks pub fn insert_chunk_batch( world: &mut World, map_id: Entity, - chunks: impl IntoIterator, + chunks: impl IntoIterator, ) { // Remove the map, or spawn an entity to hold the map, then create an empty map let mut map = remove_map::(world, map_id) @@ -781,7 +783,7 @@ pub fn insert_chunk_batch( let chunk_c = ChunkCoord(chunk_c); world.get_entity_mut(chunk_id).unwrap().insert(( Chunk::new(chunk_size.pow(N as u32)), - chunk_c, + ChunkCoord(chunk_c.0), InMap(map_id), )); map.get_chunks_mut().insert(chunk_c, chunk_id); @@ -797,8 +799,8 @@ pub fn insert_chunk_batch( pub fn take_chunk_batch( world: &mut World, map_id: Entity, - chunks: impl IntoIterator, -) -> Vec<([isize; N], Entity)> { + chunks: impl IntoIterator, +) -> Vec<([i32; N], Entity)> { // Remove the map, or return if it doesn't exist let mut map = if let Some(map_info) = remove_map::(world, map_id) { map_info @@ -815,7 +817,7 @@ pub fn take_chunk_batch( .remove::>(&ChunkCoord(chunk_c)) .and_then(|chunk_id| world.get_entity_mut(chunk_id)) { - let (chunk, _, _) = chunk_e.take::<(Chunk, ChunkCoord, InMap)>().unwrap(); + let (chunk, _, _) = chunk_e.take::<(Chunk, ChunkCoord<2>, InMap)>().unwrap(); let chunk_id = chunk_e.id(); for tile_id in chunk.0.into_iter().flatten() { if let Some(mut tile) = world.get_entity_mut(tile_id) { @@ -835,8 +837,8 @@ pub fn take_chunk_batch( pub fn take_chunk_batch_despawn_tiles( world: &mut World, map_id: Entity, - chunks: impl IntoIterator, -) -> Vec<([isize; N], Entity)> { + chunks: impl IntoIterator, +) -> Vec<([i32; N], Entity)> { // Remove the map, or return if it doesn't exist let mut map = if let Some(map_info) = remove_map::(world, map_id) { map_info @@ -853,7 +855,7 @@ pub fn take_chunk_batch_despawn_tiles( .remove::>(&ChunkCoord(chunk_c)) .and_then(|chunk_id| world.get_entity_mut(chunk_id)) { - let (chunk, _, _) = chunk_e.take::<(Chunk, ChunkCoord, InMap)>().unwrap(); + let (chunk, _, _) = chunk_e.take::<(Chunk, ChunkCoord<2>, InMap)>().unwrap(); let chunk_id = chunk_e.id(); for tile_id in chunk.0.into_iter().flatten() { world.despawn(tile_id); @@ -878,10 +880,9 @@ pub fn insert_map(world: &mut World, map_id: Entity, chunk_size: /// Despawns all the chunks and tiles in a given map pub fn despawn_children(world: &mut World, map: &mut TileMap) { - let chunks: Vec> = map.get_chunks().keys().cloned().collect(); - for chunk_c in chunks { - if let Some(old_chunk) = take_chunk_despawn_tiles_inner::(world, map, *chunk_c) { - world.despawn(old_chunk); + for (_, chunk_id) in map.get_chunks_mut().drain() { + if let Some(chunk_id) = despawn_chunk_tiles::(world, chunk_id) { + world.despawn(chunk_id); } } } diff --git a/crates/bevy_tiles/src/commands/chunk_batch.rs b/crates/bevy_tiles/src/commands/chunk_batch.rs index 19d643b..44957d8 100644 --- a/crates/bevy_tiles/src/commands/chunk_batch.rs +++ b/crates/bevy_tiles/src/commands/chunk_batch.rs @@ -4,9 +4,9 @@ use super::{insert_chunk_batch, take_chunk_batch_despawn_tiles}; pub struct SpawnChunkBatch where - F: Fn([isize; N]) -> B + Send + 'static, + F: Fn([i32; N]) -> B + Send + 'static, B: Bundle + Send + 'static, - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { pub map_id: Entity, pub chunk_cs: IC, @@ -15,12 +15,12 @@ where impl Command for SpawnChunkBatch where - F: Fn([isize; N]) -> B + Send + 'static, + F: Fn([i32; N]) -> B + Send + 'static, B: Bundle + Send + 'static, - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { fn apply(self, world: &mut World) { - let (chunk_cs, bundles): (Vec<[isize; N]>, Vec) = self + let (chunk_cs, bundles): (Vec<[i32; N]>, Vec) = self .chunk_cs .into_iter() .map(|coord| (coord, (self.bundle_f)(coord))) @@ -29,7 +29,7 @@ where let chunks = chunk_cs .into_iter() .zip(world.spawn_batch(bundles)) - .collect::>(); + .collect::>(); insert_chunk_batch::(world, self.map_id, chunks); } @@ -37,7 +37,7 @@ where pub struct DespawnChunkBatch where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { pub map_id: Entity, pub chunk_cs: IC, @@ -45,7 +45,7 @@ where impl Command for DespawnChunkBatch where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { fn apply(self, world: &mut World) { for (_, tile_id) in take_chunk_batch_despawn_tiles::(world, self.map_id, self.chunk_cs) { diff --git a/crates/bevy_tiles/src/commands/chunk_single.rs b/crates/bevy_tiles/src/commands/chunk_single.rs index 9834fdb..10b669e 100644 --- a/crates/bevy_tiles/src/commands/chunk_single.rs +++ b/crates/bevy_tiles/src/commands/chunk_single.rs @@ -4,7 +4,7 @@ use super::{insert_chunk, take_chunk_despawn_tiles}; pub struct SpawnChunk { pub map_id: Entity, - pub chunk_c: [isize; N], + pub chunk_c: [i32; N], pub chunk_id: Entity, } @@ -16,7 +16,7 @@ impl Command for SpawnChunk { pub struct DespawnChunk { pub map_id: Entity, - pub chunk_c: [isize; N], + pub chunk_c: [i32; N], } impl Command for DespawnChunk { diff --git a/crates/bevy_tiles/src/commands/tile_batch.rs b/crates/bevy_tiles/src/commands/tile_batch.rs index 0a030d2..5339acf 100644 --- a/crates/bevy_tiles/src/commands/tile_batch.rs +++ b/crates/bevy_tiles/src/commands/tile_batch.rs @@ -8,9 +8,9 @@ use super::{insert_tile_batch, take_tile_batch}; pub struct SpawnTileBatch where - F: Fn([isize; N]) -> B + Send + 'static, + F: Fn([i32; N]) -> B + Send + 'static, B: Bundle + Send + 'static, - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { pub map_id: Entity, pub tile_cs: IC, @@ -19,12 +19,12 @@ where impl Command for SpawnTileBatch where - F: Fn([isize; N]) -> B + Send + 'static, + F: Fn([i32; N]) -> B + Send + 'static, B: Bundle + Send + 'static, - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { fn apply(self, world: &mut World) { - let (tile_cs, bundles): (Vec<[isize; N]>, Vec) = self + let (tile_cs, bundles): (Vec<[i32; N]>, Vec) = self .tile_cs .into_iter() .map(|coord| (coord, (self.bundle_f)(coord))) @@ -33,7 +33,7 @@ where let tiles = tile_cs .into_iter() .zip(world.spawn_batch(bundles)) - .collect::>(); + .collect::>(); insert_tile_batch::(world, self.map_id, tiles); } @@ -41,7 +41,7 @@ where pub struct DespawnTileBatch where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { pub map_id: Entity, pub tile_cs: IC, @@ -49,7 +49,7 @@ where impl Command for DespawnTileBatch where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { fn apply(self, world: &mut World) { for (_, tile_id) in take_tile_batch::(world, self.map_id, self.tile_cs) { @@ -60,7 +60,7 @@ where pub struct MoveTileBatch where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { pub map_id: Entity, pub tile_cs: IC, @@ -68,7 +68,7 @@ where impl Command for MoveTileBatch where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { fn apply(self, world: &mut World) { const ERR_MESSAGE: &str = @@ -77,12 +77,12 @@ where let mut tile_cs = self .tile_cs .into_iter() - .collect::>(); + .collect::>(); let removed = take_tile_batch::( world, self.map_id, - tile_cs.keys().cloned().collect::>(), + tile_cs.keys().cloned().collect::>(), ) .into_iter() .map(|(tile_c, tile_id)| (tile_cs.remove(&tile_c).expect(ERR_MESSAGE), tile_id)); @@ -93,7 +93,7 @@ where pub struct SwapTileBatch where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { pub map_id: Entity, pub tile_cs: IC, @@ -101,7 +101,7 @@ where impl Command for SwapTileBatch where - IC: IntoIterator + Send + 'static, + IC: IntoIterator + Send + 'static, { fn apply(self, world: &mut World) { const ERR_MESSAGE: &str = @@ -110,12 +110,12 @@ where let tile_cs = self .tile_cs .into_iter() - .collect::>(); + .collect::>(); let removed_left = take_tile_batch::( world, self.map_id, - tile_cs.left_values().cloned().collect::>(), + tile_cs.left_values().cloned().collect::>(), ) .into_iter() .map(|(tile_c, tile_id)| (*tile_cs.get_by_left(&tile_c).expect(ERR_MESSAGE), tile_id)); @@ -123,7 +123,7 @@ where let removed_right = take_tile_batch::( world, self.map_id, - tile_cs.right_values().cloned().collect::>(), + tile_cs.right_values().cloned().collect::>(), ) .into_iter() .map(|(tile_c, tile_id)| (*tile_cs.get_by_right(&tile_c).expect(ERR_MESSAGE), tile_id)); diff --git a/crates/bevy_tiles/src/commands/tile_single.rs b/crates/bevy_tiles/src/commands/tile_single.rs index 004e724..6048903 100644 --- a/crates/bevy_tiles/src/commands/tile_single.rs +++ b/crates/bevy_tiles/src/commands/tile_single.rs @@ -4,7 +4,7 @@ use super::{insert_tile, insert_tile_into_map, remove_map, take_tile, take_tile_ pub struct SpawnTile { pub map_id: Entity, - pub tile_c: [isize; N], + pub tile_c: [i32; N], pub tile_id: Entity, } @@ -16,7 +16,7 @@ impl Command for SpawnTile { pub struct DespawnTile { pub map_id: Entity, - pub tile_c: [isize; N], + pub tile_c: [i32; N], } impl Command for DespawnTile { @@ -30,8 +30,8 @@ impl Command for DespawnTile { pub struct SwapTile { pub map_id: Entity, - pub tile_c_1: [isize; N], - pub tile_c_2: [isize; N], + pub tile_c_1: [i32; N], + pub tile_c_2: [i32; N], } impl Command for SwapTile { @@ -62,8 +62,8 @@ impl Command for SwapTile { pub struct MoveTile { pub map_id: Entity, - pub old_c: [isize; N], - pub new_c: [isize; N], + pub old_c: [i32; N], + pub new_c: [i32; N], } impl Command for MoveTile { diff --git a/crates/bevy_tiles/src/coords.rs b/crates/bevy_tiles/src/coords.rs index 61972f7..6286981 100644 --- a/crates/bevy_tiles/src/coords.rs +++ b/crates/bevy_tiles/src/coords.rs @@ -1,37 +1,36 @@ /// Calculate the coordinate of a chunk from a given tile coordinate and chunk size #[inline] pub fn calculate_chunk_coordinate( - mut tile_c: [isize; N], + tile_c: impl Into<[i32; N]>, chunk_size: usize, -) -> [isize; N] { - for i in tile_c.iter_mut() { - if *i < 0 { - *i = (*i + 1) / (chunk_size as isize) - 1; +) -> [i32; N] { + tile_c.into().map(|i| { + if i < 0 { + (i + 1) / (chunk_size as i32) - 1 } else { - *i /= chunk_size as isize; + i / chunk_size as i32 } - } - tile_c + }) } /// Calculate the coordinate of a tile relative to the origin of it's chunk. #[inline] pub fn calculate_chunk_relative_tile_coordinate( - mut tile_c: [isize; N], + tile_c: impl Into<[i32; N]>, chunk_size: usize, -) -> [isize; N] { - for i in tile_c.iter_mut() { - *i %= chunk_size as isize; - if *i < 0 { - *i += chunk_size as isize; +) -> [i32; N] { + tile_c.into().map(|mut i| { + i %= chunk_size as i32; + if i < 0 { + i += chunk_size as i32; } - } - tile_c + i + }) } /// Calculate the index of a tile within it's chunk. #[inline] -pub fn calculate_tile_index(tile_c: [isize; N], chunk_size: usize) -> usize { +pub fn calculate_tile_index(tile_c: [i32; N], chunk_size: usize) -> usize { let mut index = 0; let relative_tile_c = calculate_chunk_relative_tile_coordinate(tile_c, chunk_size); for (i, c) in relative_tile_c.iter().enumerate() { @@ -43,16 +42,16 @@ pub fn calculate_tile_index(tile_c: [isize; N], chunk_size: usiz /// Calculate the coordinate of a tile from it's index in a chunk, and the chunk coordinate. #[inline] pub fn calculate_tile_coordinate( - chunk_c: [isize; N], + chunk_c: [i32; N], tile_i: usize, chunk_size: usize, -) -> [isize; N] { - let mut chunk_world_c = chunk_c.map(|c| c * chunk_size as isize); +) -> [i32; N] { + let mut chunk_world_c = chunk_c.map(|c| c * chunk_size as i32); for (i, c) in chunk_world_c.iter_mut().enumerate() { if i == 0 { - *c += (tile_i % chunk_size) as isize; + *c += (tile_i % chunk_size) as i32; } else { - *c += (tile_i / chunk_size.pow(i as u32)) as isize; + *c += (tile_i / chunk_size.pow(i as u32)) as i32; } } chunk_world_c @@ -73,21 +72,23 @@ pub fn max_tile_index(chunk_size: usize) -> usize { /// (For example, if tiles are being represented by 16x16 pixel sprites, /// the scale factor should be set to 16) #[inline] -pub fn world_to_tile(world_c: [f32; N], scale_f: f32) -> [isize; N] { - world_c.map(|c| (c / scale_f - if c < 0.0 { 1.0 } else { 0.0 }) as isize) +pub fn world_to_tile(world_c: impl Into<[f32; N]>, scale_f: f32) -> [i32; N] { + world_c + .into() + .map(|c| (c / scale_f - if c < 0.0 { 1.0 } else { 0.0 }) as i32) } /// Allows for iteration between all coordinates in between two corners. pub struct CoordIterator { - corner_1: [isize; N], - corner_2: [isize; N], - current: [isize; N], + corner_1: [i32; N], + corner_2: [i32; N], + current: [i32; N], complete: bool, } impl CoordIterator { /// Create an iterator that iterates through each point created by the bounding of two corners. - pub fn new(mut corner_1: [isize; N], mut corner_2: [isize; N]) -> Self { + pub fn new(mut corner_1: [i32; N], mut corner_2: [i32; N]) -> Self { for i in 0..N { if corner_1[i] > corner_2[i] { std::mem::swap(&mut corner_1[i], &mut corner_2[i]); @@ -104,7 +105,7 @@ impl CoordIterator { } impl Iterator for CoordIterator { - type Item = [isize; N]; + type Item = [i32; N]; #[inline] fn next(&mut self) -> Option { @@ -138,7 +139,7 @@ mod tests { use super::*; - fn make_range_iter(val_1: isize, val_2: isize) -> RangeInclusive { + fn make_range_iter(val_1: i32, val_2: i32) -> RangeInclusive { if val_1 < val_2 { val_1..=val_2 } else { @@ -153,7 +154,7 @@ mod tests { #[case([0, 3, 0], [3, 3, 3])] #[case([0, 3, 0], [0, 0, 3])] #[case([3, 3, 3], [3, 3, 3])] - fn coord_iter(#[case] corner_1: [isize; 3], #[case] corner_2: [isize; 3]) { + fn coord_iter(#[case] corner_1: [i32; 3], #[case] corner_2: [i32; 3]) { let mut iter = CoordIterator::new(corner_1, corner_2); for z in make_range_iter(corner_1[2], corner_2[2]) { @@ -178,11 +179,7 @@ mod tests { #[case(16, [-1, -1], 255)] #[case(16, [-16, -16], 0)] #[case(8, [-8, -0], 0)] - fn tile_index_test( - #[case] chunk_size: usize, - #[case] tile_c: [isize; 2], - #[case] index: usize, - ) { + fn tile_index_test(#[case] chunk_size: usize, #[case] tile_c: [i32; 2], #[case] index: usize) { assert_eq!(calculate_tile_index(tile_c, chunk_size), index) } } diff --git a/crates/bevy_tiles/src/lib.rs b/crates/bevy_tiles/src/lib.rs index 80ec0a0..6da5394 100644 --- a/crates/bevy_tiles/src/lib.rs +++ b/crates/bevy_tiles/src/lib.rs @@ -20,15 +20,56 @@ pub mod maps; /// Provides tile level utilities. pub mod tiles; -/// Provides most of what you need to get started. -pub mod prelude { - pub use crate::commands::{TileCommandExt, TileMapCommands}; - - pub use crate::chunks::*; - pub use crate::coords::*; - pub use crate::maps::*; - pub use crate::tiles::*; - pub use crate::TilesPlugin; +/// Helper aliases for working with 2d grids +pub mod tiles_2d { + use bevy::ecs::system::Commands; + + /// 2d [crate::tiles::TileCoord] alias. + pub type TileCoord = crate::tiles::TileCoord<2>; + + /// 2d [crate::tiles::TileMapQuery] alias. + pub type TileMapQuery<'w, 's, Q, F = ()> = crate::tiles::TileMapQuery<'w, 's, Q, F, 2>; + + /// 2d [crate::chunks::ChunkCoord] alias. + pub type ChunkCoord = crate::chunks::ChunkCoord<2>; + + /// 2d [crate::chunks::ChunkMapQuery] alias. + pub type ChunkMapQuery<'w, 's, Q, F = ()> = crate::chunks::ChunkMapQuery<'w, 's, Q, F, 2>; + + /// 2d [crate::commands::TileMapCommands] alias. + pub type TileMapCommands<'a, 'w, 's, const N: usize> = + crate::commands::TileMapCommands<'a, 'w, 's, 2>; + + /// 2d [crate::commands::TileCommandExt] alias. + pub trait TileCommandExt<'w, 's>: crate::commands::TileCommandExt<'w, 's, 2> {} + + impl<'w, 's> TileCommandExt<'w, 's> for Commands<'w, 's> {} +} + +/// Helper aliases for working with 2d grids +pub mod tiles_3d { + use bevy::ecs::system::Commands; + + /// 3d [crate::tiles::TileCoord] alias. + pub type TileCoord = crate::tiles::TileCoord<3>; + + /// 3d [crate::tiles::TileMapQuery] alias. + pub type TileMapQuery<'w, 's, Q, F = ()> = crate::tiles::TileMapQuery<'w, 's, Q, F, 3>; + + /// 3d [crate::chunks::ChunkCoord] alias. + pub type ChunkCoord = crate::chunks::ChunkCoord<3>; + + /// 3d [crate::chunks::ChunkMapQuery] alias. + pub type ChunkMapQuery<'w, 's, Q, F = ()> = crate::chunks::ChunkMapQuery<'w, 's, Q, F, 3>; + + /// 3d [crate::commands::TileMapCommands] alias. + pub type TileMapCommands<'a, 'w, 's, const N: usize> = + crate::commands::TileMapCommands<'a, 'w, 's, 3>; + + /// 3d [crate::commands::TileCommandExt] alias. + pub trait TileCommandExt<'w, 's>: crate::commands::TileCommandExt<'w, 's, 3> {} + + impl<'w, 's> TileCommandExt<'w, 's> for Commands<'w, 's> {} } /// Adds Tiles dependencies to the App. diff --git a/crates/bevy_tiles/src/maps.rs b/crates/bevy_tiles/src/maps.rs index ef1f7e4..84e6200 100644 --- a/crates/bevy_tiles/src/maps.rs +++ b/crates/bevy_tiles/src/maps.rs @@ -3,7 +3,7 @@ use bevy::{ utils::HashMap, }; -use crate::{chunks::ChunkCoord, prelude::calculate_chunk_coordinate, tiles::TileCoord}; +use crate::{chunks::ChunkCoord, coords::calculate_chunk_coordinate, tiles::TileCoord}; /// Holds handles to all the chunks in a map. /// # Note diff --git a/crates/bevy_tiles/src/tiles.rs b/crates/bevy_tiles/src/tiles.rs index bf34a0a..b29da8f 100644 --- a/crates/bevy_tiles/src/tiles.rs +++ b/crates/bevy_tiles/src/tiles.rs @@ -5,12 +5,44 @@ mod tile_query; pub use tile_query::*; /// The index of a tile in a given chunk. -#[derive(Component, Deref, Debug)] +/// # Note: +/// It probably won't break anything to manually copy this +/// to put it on your own entities, but this is only accurate +/// when mutated by the plugin. +#[derive(Component, Clone, Copy, PartialEq, Eq, Deref, Debug)] pub struct TileIndex(pub(crate) usize); /// The coordinate of a tile in a given map. -#[derive(Component, Deref, Debug)] -pub struct TileCoord(pub(crate) [isize; N]); +/// # Note: +/// It probably won't break anything to manually copy this +/// to put it on your own entities, but this is only accurate +/// when mutated by the plugin. +#[derive(Component, Deref, Clone, Copy, PartialEq, Eq, Debug)] +pub struct TileCoord(pub(crate) [i32; N]); + +impl From> for IVec3 { + fn from(value: TileCoord<3>) -> Self { + value.0.into() + } +} + +impl From> for IVec2 { + fn from(value: TileCoord<2>) -> Self { + value.0.into() + } +} + +impl From> for Vec3 { + fn from(value: TileCoord<3>) -> Self { + Vec3::new(value[0] as f32, value[1] as f32, value[2] as f32) + } +} + +impl From> for Vec2 { + fn from(value: TileCoord<2>) -> Self { + Vec2::new(value[0] as f32, value[1] as f32) + } +} /// A relation on tiles that point towards the chunk they are a part of. #[derive(Component, Deref, Debug)] diff --git a/crates/bevy_tiles/src/tiles/tile_query.rs b/crates/bevy_tiles/src/tiles/tile_query.rs index b18e320..0309d98 100644 --- a/crates/bevy_tiles/src/tiles/tile_query.rs +++ b/crates/bevy_tiles/src/tiles/tile_query.rs @@ -1,7 +1,4 @@ -use std::{ - marker::PhantomData, - ops::{Deref, DerefMut}, -}; +use std::ops::{Deref, DerefMut}; use bevy::{ ecs::{ @@ -14,66 +11,12 @@ use bevy::{ use crate::{ chunks::{Chunk, InMap}, + coords::{calculate_tile_coordinate, calculate_tile_index, max_tile_index, CoordIterator}, maps::TileMap, - prelude::{calculate_tile_coordinate, calculate_tile_index, max_tile_index, CoordIterator}, }; use super::{InChunk, TileCoord}; -/// Borrowed types from a [TileMapQuery] needed to construct a [TileQuery] -pub struct BorrowedTileQueries<'a, 'w: 'a, 's: 'a, Q, F, const N: usize> -where - Q: QueryData + 'static, - F: QueryFilter + 'static, -{ - phantom: PhantomData<(&'a Q, &'w F, &'s Q)>, -} - -impl<'a, 'w: 'a, 's: 'a, Q, F, const N: usize> BorrowedTileQueryTypes<'a> - for BorrowedTileQueries<'a, 'w, 's, Q, F, N> -where - Q: QueryData + 'static, - F: QueryFilter + 'static, -{ - type TileQuery = &'a Query<'w, 's, Q, (F, With)>; - - type ChunkQuery = &'a Query<'w, 's, &'static Chunk, With>; - - type Map = &'a TileMap; -} - -/// Mutable borrowed types from a [TileMapQuery] needed to construct a mutable [TileQuery] -pub struct MutableBorrowedTileQueries<'a, 'w: 'a, 's: 'a, Q, F, const N: usize> -where - Q: QueryData + 'static, - F: QueryFilter + 'static, -{ - phantom: PhantomData<(&'a Q, &'w F, &'s Q)>, -} - -impl<'a, 'w: 'a, 's: 'a, Q, F, const N: usize> BorrowedTileQueryTypes<'a> - for MutableBorrowedTileQueries<'a, 'w, 's, Q, F, N> -where - Q: QueryData + 'static, - F: QueryFilter + 'static, -{ - type TileQuery = &'a mut Query<'w, 's, Q, (F, With)>; - - type ChunkQuery = &'a mut Query<'w, 's, &'static Chunk, With>; - - type Map = &'a TileMap; -} - -/// Describes the types used to construct a query, mainly needed to reduce code duplication. -pub trait BorrowedTileQueryTypes<'a> { - /// Query for tiles. - type TileQuery; - /// Query for chunks. - type ChunkQuery; - /// The map used. - type Map; -} - /// Used to query individual tiles from a tile map. /// This query also implicitly queries chunks and maps /// in order to properly resolve tiles. @@ -148,7 +91,8 @@ where Q: QueryData + 'static, F: QueryFilter + 'static, { - fn get_tile_entity(&self, tile_c: [isize; N]) -> Option { + fn get_tile_entity(&self, tile_c: impl Into<[i32; N]>) -> Option { + let tile_c = tile_c.into(); let chunk_size = self.map.get_chunk_size(); let chunk_id = self.map.get_from_tile(TileCoord::(tile_c))?; @@ -161,8 +105,9 @@ where /// Gets the readonly query item for the given tile. pub fn get_at( &self, - tile_c: [isize; N], + tile_c: impl Into<[i32; N]>, ) -> Option<<::ReadOnly as WorldQuery>::Item<'_>> { + let tile_c = tile_c.into(); let tile_e = self.get_tile_entity(tile_c)?; self.tile_q.get(tile_e).ok() } @@ -172,8 +117,9 @@ where /// This function makes it possible to violate Rust's aliasing guarantees: please use responsibly. pub unsafe fn get_at_unchecked( &self, - tile_c: [isize; N], + tile_c: impl Into<[i32; N]>, ) -> Option<::Item<'_>> { + let tile_c = tile_c.into(); let tile_e = self.get_tile_entity(tile_c)?; self.tile_q.get_unchecked(tile_e).ok() } @@ -182,16 +128,19 @@ where /// inclusive over `corner_2` pub fn iter_in( &self, - corner_1: [isize; N], - corner_2: [isize; N], + corner_1: impl Into<[i32; N]>, + corner_2: impl Into<[i32; N]>, ) -> TileQueryIter<'_, 'a, T, C, N> { + let corner_1 = corner_1.into(); + let corner_2 = corner_2.into(); TileQueryIter::new(self, corner_1, corner_2) } /// Iter all tiles in a given chunk. /// # Note /// The coordinates for this function are givne in chunk coordinates. - pub fn iter_in_chunk(&self, chunk_c: [isize; N]) -> TileQueryIter<'_, 'a, T, C, N> { + pub fn iter_in_chunk(&self, chunk_c: impl Into<[i32; N]>) -> TileQueryIter<'_, 'a, T, C, N> { + let chunk_c = chunk_c.into(); let chunk_size = self.map.get_chunk_size(); // Get corners of chunk let corner_1 = calculate_tile_coordinate(chunk_c, 0, chunk_size); @@ -206,9 +155,11 @@ where /// The coordinates for this function are givne in chunk coordinates. pub fn iter_in_chunks( &mut self, - chunk_c_1: [isize; N], - chunk_c_2: [isize; N], + chunk_c_1: impl Into<[i32; N]>, + chunk_c_2: impl Into<[i32; N]>, ) -> TileQueryIter<'_, 'a, T, C, N> { + let chunk_c_1 = chunk_c_1.into(); + let chunk_c_2 = chunk_c_2.into(); let chunk_size = self.map.get_chunk_size(); // Get corners of chunk let corner_1 = calculate_tile_coordinate(chunk_c_1, 0, chunk_size); @@ -227,7 +178,10 @@ where F: QueryFilter + 'static, { /// Gets the query item for the given tile. - pub fn get_at_mut(&mut self, tile_c: [isize; N]) -> Option<::Item<'_>> { + pub fn get_at_mut( + &mut self, + tile_c: impl Into<[i32; N]>, + ) -> Option<::Item<'_>> { let tile_e = self.get_tile_entity(tile_c)?; self.tile_q.get_mut(tile_e).ok() } @@ -237,9 +191,11 @@ where /// The coordinates for this function are givne in chunk coordinates. pub fn iter_in_chunks_mut( &mut self, - chunk_c_1: [isize; N], - chunk_c_2: [isize; N], + chunk_c_1: impl Into<[i32; N]>, + chunk_c_2: impl Into<[i32; N]>, ) -> TileQueryIterMut<'_, 'a, T, C, N> { + let chunk_c_1 = chunk_c_1.into(); + let chunk_c_2 = chunk_c_2.into(); let chunk_size = self.map.get_chunk_size(); // Get corners of chunk let corner_1 = calculate_tile_coordinate(chunk_c_1, 0, chunk_size); @@ -252,7 +208,11 @@ where /// Iter all tiles in a given chunk. /// # Note /// The coordinates for this function are givne in chunk coordinates. - pub fn iter_in_chunk_mut(&mut self, chunk_c: [isize; N]) -> TileQueryIterMut<'_, 'a, T, C, N> { + pub fn iter_in_chunk_mut( + &mut self, + chunk_c: impl Into<[i32; N]>, + ) -> TileQueryIterMut<'_, 'a, T, C, N> { + let chunk_c = chunk_c.into(); let chunk_size = self.map.get_chunk_size(); // Get corners of chunk let corner_1 = calculate_tile_coordinate(chunk_c, 0, chunk_size); @@ -266,9 +226,11 @@ where /// inclusive over `corner_2` pub fn iter_in_mut( &mut self, - corner_1: [isize; N], - corner_2: [isize; N], + corner_1: impl Into<[i32; N]>, + corner_2: impl Into<[i32; N]>, ) -> TileQueryIterMut<'_, 'a, T, C, N> { + let corner_1 = corner_1.into(); + let corner_2 = corner_2.into(); TileQueryIterMut::new(self, corner_1, corner_2) } } @@ -280,7 +242,7 @@ pub struct TileQueryIter<'i, 'a, T, C, const N: usize> { } impl<'i, 'a: 'i, T, C, const N: usize> TileQueryIter<'i, 'a, T, C, N> { - fn new(tile_q: &'i TileQuery<'a, T, C, N>, corner_1: [isize; N], corner_2: [isize; N]) -> Self { + fn new(tile_q: &'i TileQuery<'a, T, C, N>, corner_1: [i32; N], corner_2: [i32; N]) -> Self { Self { tile_q, coord_iter: CoordIterator::new(corner_1, corner_2), @@ -327,11 +289,7 @@ pub struct TileQueryIterMut<'i, 'a, T, C, const N: usize> { } impl<'i, 'a: 'i, T, C, const N: usize> TileQueryIterMut<'i, 'a, T, C, N> { - fn new( - tile_q: &'i mut TileQuery<'a, T, C, N>, - corner_1: [isize; N], - corner_2: [isize; N], - ) -> Self { + fn new(tile_q: &'i mut TileQuery<'a, T, C, N>, corner_1: [i32; N], corner_2: [i32; N]) -> Self { Self { tile_q, coord_iter: CoordIterator::new(corner_1, corner_2), From 403813be0e074eec0b9903d77999c595c3c9490c Mon Sep 17 00:00:00 2001 From: James Bell Date: Sat, 20 Apr 2024 14:04:26 -0400 Subject: [PATCH 2/4] Cleanup and add warnings --- crates/bevy_tiles/examples/basic_2d.rs | 2 +- crates/bevy_tiles/examples/basic_3d.rs | 2 +- crates/bevy_tiles/src/coords.rs | 4 +++- crates/bevy_tiles/src/tiles/tile_query.rs | 3 +++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/bevy_tiles/examples/basic_2d.rs b/crates/bevy_tiles/examples/basic_2d.rs index 7a5923b..efb594a 100644 --- a/crates/bevy_tiles/examples/basic_2d.rs +++ b/crates/bevy_tiles/examples/basic_2d.rs @@ -43,7 +43,7 @@ fn spawn(mut commands: Commands, asset_server: Res) { // spawn a player map.spawn_tile( - [0, 0], + IVec2::ZERO, ( Character, SpriteBundle { diff --git a/crates/bevy_tiles/examples/basic_3d.rs b/crates/bevy_tiles/examples/basic_3d.rs index b2dd6ee..1dde36d 100644 --- a/crates/bevy_tiles/examples/basic_3d.rs +++ b/crates/bevy_tiles/examples/basic_3d.rs @@ -69,7 +69,7 @@ fn spawn( // spawn a player tile_commands.spawn_tile( - [0, 0, 0], + IVec3::ZERO, ( Character, PbrBundle { diff --git a/crates/bevy_tiles/src/coords.rs b/crates/bevy_tiles/src/coords.rs index 6286981..7bd4d70 100644 --- a/crates/bevy_tiles/src/coords.rs +++ b/crates/bevy_tiles/src/coords.rs @@ -88,7 +88,9 @@ pub struct CoordIterator { impl CoordIterator { /// Create an iterator that iterates through each point created by the bounding of two corners. - pub fn new(mut corner_1: [i32; N], mut corner_2: [i32; N]) -> Self { + pub fn new(corner_1: impl Into<[i32; N]>, corner_2: impl Into<[i32; N]>) -> Self { + let mut corner_1 = corner_1.into(); + let mut corner_2 = corner_2.into(); for i in 0..N { if corner_1[i] > corner_2[i] { std::mem::swap(&mut corner_1[i], &mut corner_2[i]); diff --git a/crates/bevy_tiles/src/tiles/tile_query.rs b/crates/bevy_tiles/src/tiles/tile_query.rs index 0309d98..1d3a09d 100644 --- a/crates/bevy_tiles/src/tiles/tile_query.rs +++ b/crates/bevy_tiles/src/tiles/tile_query.rs @@ -283,6 +283,9 @@ where ///# } /// ``` /// Iterates over all the tiles in a region. +// DO TO UNSAFE DATA ACCESS INSIDE THIS ITERATOR +// DO NOT CONSTRUCT THIS WITH ARBITRARY TILE ACCESSES +// ONLY USE COORD ITERATORS WHICH ENSURE A GIVEN COORD IS RETURNED ONCE. pub struct TileQueryIterMut<'i, 'a, T, C, const N: usize> { coord_iter: CoordIterator, tile_q: &'i TileQuery<'a, T, C, N>, From 7170af775c5c360ca9dfb8ed0089b6fa2236b3c6 Mon Sep 17 00:00:00 2001 From: James Bell Date: Sat, 20 Apr 2024 14:06:49 -0400 Subject: [PATCH 3/4] Update version --- crates/bevy_tiles/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_tiles/Cargo.toml b/crates/bevy_tiles/Cargo.toml index d319b8b..0bc4a85 100644 --- a/crates/bevy_tiles/Cargo.toml +++ b/crates/bevy_tiles/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bevy_tiles" -version.workspace = true +version = 0.1.0 edition.workspace = true authors.workspace = true license-file.workspace = true From e42d3bc0148d933d2092913e213c69db6369c716 Mon Sep 17 00:00:00 2001 From: James Bell Date: Sat, 20 Apr 2024 15:13:15 -0400 Subject: [PATCH 4/4] Fix version --- Cargo.lock | 2 +- crates/bevy_tiles/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a53bea6..a1416d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "bevy_tiles" -version = "0.0.0-dev3" +version = "0.1.0" dependencies = [ "bevy", "bimap", diff --git a/crates/bevy_tiles/Cargo.toml b/crates/bevy_tiles/Cargo.toml index 0bc4a85..cb73697 100644 --- a/crates/bevy_tiles/Cargo.toml +++ b/crates/bevy_tiles/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bevy_tiles" -version = 0.1.0 +version = "0.1.0" edition.workspace = true authors.workspace = true license-file.workspace = true