Skip to content

Commit

Permalink
Tile removal with despawn.
Browse files Browse the repository at this point in the history
  • Loading branch information
StarArawn committed May 13, 2022
1 parent 70793d7 commit 365740f
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 43 deletions.
8 changes: 4 additions & 4 deletions examples/game_of_life.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bevy_ecs_tilemap::{
Tilemap2dGridSize, Tilemap2dSize, Tilemap2dTextureSize, Tilemap2dTileSize, TilemapId,
TilemapTexture,
},
tiles::{Tile2dStorage, TileBundle, TilePos2d, TileTexture, TileVisible},
tiles::{Tile2dStorage, TileBundle, TilePos2d, TileVisible},
Tilemap2dPlugin, TilemapBundle,
};

Expand All @@ -15,7 +15,7 @@ fn startup(mut commands: Commands, asset_server: Res<AssetServer>) {

let texture_handle: Handle<Image> = asset_server.load("tiles.png");

let tilemap_size = Tilemap2dSize { x: 80, y: 80 };
let tilemap_size = Tilemap2dSize { x: 512, y: 512 };
let mut tile_storage = Tile2dStorage::empty(tilemap_size);
let tilemap_entity = commands.spawn().id();

Expand Down Expand Up @@ -65,12 +65,12 @@ fn update(
mut commands: Commands,
time: Res<Time>,
mut tile_storage_query: Query<(&Tile2dStorage, &mut LastUpdate)>,
tile_query: Query<(Entity, &TilePos2d, &TileTexture, &TileVisible)>,
tile_query: Query<(Entity, &TilePos2d, &TileVisible)>,
) {
let current_time = time.seconds_since_startup();
let (tile_storage, mut last_update) = tile_storage_query.single_mut();
if current_time - last_update.0 > 0.1 {
for (entity, position, tile_texture, visibility) in tile_query.iter() {
for (entity, position, visibility) in tile_query.iter() {
let neighbor_count = tile_storage
.get_tile_neighbors(position)
.iter()
Expand Down
4 changes: 2 additions & 2 deletions examples/remove_tiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bevy_ecs_tilemap::{
Tilemap2dGridSize, Tilemap2dSize, Tilemap2dTextureSize, Tilemap2dTileSize, TilemapId,
TilemapTexture,
},
tiles::{RemoveTile, Tile2dStorage, TileBundle, TilePos2d},
tiles::{Tile2dStorage, TileBundle, TilePos2d},
Tilemap2dPlugin, TilemapBundle,
};
use rand::{thread_rng, Rng};
Expand Down Expand Up @@ -77,7 +77,7 @@ fn remove_tiles(
};

if let Some(tile_entity) = tile_storage.get(&position) {
commands.entity(tile_entity).insert(RemoveTile);
commands.entity(tile_entity).despawn_recursive();
// Don't forget to remove tiles from the tile storage!
tile_storage.set(&position, None);
}
Expand Down
25 changes: 22 additions & 3 deletions src/render/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::hash::{Hash, Hasher};

use bevy::{
math::{UVec2, UVec3, UVec4, Vec2, Vec3Swizzles, Vec4, Vec4Swizzles},
prelude::{Component, Mesh, Transform},
prelude::{Component, Entity, Mesh, Transform},
render::{
mesh::{GpuBufferInfo, GpuMesh, Indices, VertexAttributeValues},
render_resource::{std140::AsStd140, BufferInitDescriptor, BufferUsages},
Expand All @@ -19,6 +19,7 @@ use crate::{
#[derive(Default, Clone, Debug)]
pub struct RenderChunk2dStorage {
chunks: HashMap<u32, HashMap<UVec3, RenderChunk2d>>,
entity_to_chunk_tile: HashMap<Entity, (u32, UVec3, UVec2)>,
}

#[derive(Default, Component, Clone, Copy, Debug)]
Expand All @@ -27,6 +28,8 @@ pub struct ChunkId(pub UVec3);
impl RenderChunk2dStorage {
pub fn get_or_add(
&mut self,
tile_entity: Entity,
tile_pos: UVec2,
position: &UVec4,
chunk_size: UVec2,
mesh_type: TilemapMeshType,
Expand All @@ -37,10 +40,13 @@ impl RenderChunk2dStorage {
map_size: Tilemap2dSize,
transform: Transform,
) -> &mut RenderChunk2d {
let chunk_storage = self.get_chunk_storage(position);

let pos = position.xyz();

self.entity_to_chunk_tile
.insert(tile_entity, (position.w, pos, tile_pos));

let chunk_storage = self.get_chunk_storage(position);

let mut hasher = std::collections::hash_map::DefaultHasher::new();
position.hash(&mut hasher);

Expand Down Expand Up @@ -75,6 +81,19 @@ impl RenderChunk2dStorage {
chunk_storage.get_mut(&position.xyz()).unwrap()
}

pub fn get_mut_from_entity(&mut self, entity: Entity) -> Option<(&mut RenderChunk2d, UVec2)> {
// dbg!(&self.entity_to_chunk_tile);

if !self.entity_to_chunk_tile.contains_key(&entity) {
return None;
}

let (tilemap_id, chunk_pos, tile_pos) = self.entity_to_chunk_tile.get(&entity).unwrap();

let chunk_storage = self.chunks.get_mut(&tilemap_id).unwrap();
Some((chunk_storage.get_mut(&chunk_pos.xyz()).unwrap(), *tile_pos))
}

pub fn get_chunk_storage(&mut self, position: &UVec4) -> &mut HashMap<UVec3, RenderChunk2d> {
if self.chunks.contains_key(&position.w) {
self.chunks.get_mut(&position.w).unwrap()
Expand Down
31 changes: 11 additions & 20 deletions src/render/extract.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use bevy::{
math::Vec4,
prelude::{
Added, Bundle, Changed, Commands, Component, DespawnRecursiveExt, Entity, Or, Query,
Transform, With,
},
prelude::{Added, Bundle, Changed, Commands, Component, Entity, Or, Query, Transform},
utils::HashMap,
};

Expand All @@ -12,13 +9,14 @@ use crate::{
Tilemap2dSize, Tilemap2dSpacing, Tilemap2dTextureSize, Tilemap2dTileSize, TilemapId,
TilemapMeshType, TilemapTexture,
},
tiles::{RemoveTile, TileFlip, TilePos2d, TileTexture, TileVisible},
tiles::{TileFlip, TilePos2d, TileTexture, TileVisible},
};

use super::chunk::PackedTileData;
use super::{chunk::PackedTileData, RemovedTileEntity};

#[derive(Component)]
pub struct ExtractedTile {
pub entity: Entity,
pub position: TilePos2d,
pub tile: PackedTileData,
pub tilemap_id: TilemapId,
Expand All @@ -31,9 +29,7 @@ pub struct ExtractedTileBundle {

#[derive(Component)]
pub struct ExtractedRemovedTile {
pub position: TilePos2d,
pub tilemap_id: TilemapId,
pub layer: u32,
pub entity: Entity,
}

#[derive(Bundle)]
Expand Down Expand Up @@ -120,6 +116,7 @@ pub fn extract(
entity,
ExtractedTileBundle {
tile: ExtractedTile {
entity,
position: *tile_pos,
tile,
tilemap_id: *tilemap_id,
Expand All @@ -137,23 +134,17 @@ pub fn extract(

pub fn extract_removal(
mut commands: Commands,
removed_tiles_query: Query<(Entity, &TilePos2d, &TilemapId), With<RemoveTile>>,
tilemap_query: Query<&Transform>,
// removed_tiles_query: Query<(Entity, &, &TilemapId), With<RemoveTile>>,
removed_tiles_query: Query<&RemovedTileEntity>,
) {
let mut removed_tiles: Vec<(Entity, ExtractedRemovedTileBundle)> = Vec::new();
for (entity, position, tilemap_id) in removed_tiles_query.iter() {
let transform = tilemap_query.get(tilemap_id.0).unwrap();
for entity in removed_tiles_query.iter() {
removed_tiles.push((
entity,
entity.0,
ExtractedRemovedTileBundle {
tile: ExtractedRemovedTile {
position: *position,
tilemap_id: *tilemap_id,
layer: transform.translation.z as u32,
},
tile: ExtractedRemovedTile { entity: entity.0 },
},
));
commands.entity(entity).despawn_recursive();
}

commands.insert_or_spawn_batch(removed_tiles);
Expand Down
25 changes: 24 additions & 1 deletion src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use std::marker::PhantomData;

use bevy::{
core_pipeline::Transparent2d,
prelude::{Assets, Component, Plugin, Shader},
prelude::{
Assets, Commands, Component, CoreStage, Entity, Plugin, Query, RemovedComponents, Shader,
With,
},
render::{
mesh::MeshVertexAttribute,
render_phase::AddRenderCommand,
Expand All @@ -11,6 +14,8 @@ use bevy::{
},
};

use crate::tiles::TilePos2d;

use self::{
chunk::{RenderChunk2dStorage, TilemapUniformData},
draw::DrawTilemap,
Expand All @@ -36,6 +41,9 @@ pub struct Tilemap2dRenderingPlugin;

impl Plugin for Tilemap2dRenderingPlugin {
fn build(&self, app: &mut bevy::prelude::App) {
app.add_system_to_stage(CoreStage::First, clear_removed);
app.add_system_to_stage(CoreStage::PostUpdate, removal_helper);

let mut shaders = app.world.get_resource_mut::<Assets<Shader>>().unwrap();

let tilemap_shader = include_str!("shaders/tilemap-atlas.wgsl");
Expand Down Expand Up @@ -138,3 +146,18 @@ pub const ATTRIBUTE_TEXTURE: MeshVertexAttribute =
MeshVertexAttribute::new("Texture", 222922753, VertexFormat::Float32x4);
pub const ATTRIBUTE_COLOR: MeshVertexAttribute =
MeshVertexAttribute::new("Color", 231497124, VertexFormat::Float32x4);

#[derive(Component)]
pub struct RemovedTileEntity(pub Entity);

fn removal_helper(mut commands: Commands, removed_query: RemovedComponents<TilePos2d>) {
for entity in removed_query.iter() {
commands.spawn().insert(RemovedTileEntity(entity));
}
}

fn clear_removed(mut commands: Commands, removed_query: Query<Entity, With<RemovedTileEntity>>) {
for entity in removed_query.iter() {
commands.entity(entity).despawn();
}
}
18 changes: 5 additions & 13 deletions src/render/prepare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ pub fn prepare(
);

let chunk = chunk_storage.get_or_add(
tile.entity,
map_tile_to_chunk_tile(&tile.position, &chunk_pos).into(),
&chunk_data,
CHUNK_SIZE_2D,
*mesh_type,
Expand Down Expand Up @@ -139,18 +141,8 @@ pub fn prepare_removal(
removed_tiles: Query<&ExtractedRemovedTile>,
) {
for removed_tile in removed_tiles.iter() {
let chunk_pos = map_tile_to_chunk(&removed_tile.position);
let chunk_data = UVec4::new(
chunk_pos.x,
chunk_pos.y,
removed_tile.layer,
removed_tile.tilemap_id.0.id(),
);
let chunk = chunk_storage.get_mut(&chunk_data);

chunk.set(
&map_tile_to_chunk_tile(&removed_tile.position, &chunk_pos).into(),
None,
);
if let Some((chunk, tile_pos)) = chunk_storage.get_mut_from_entity(removed_tile.entity) {
chunk.set(&tile_pos.into(), None);
}
}
}

0 comments on commit 365740f

Please sign in to comment.