Skip to content

Commit 04c2b32

Browse files
TilemapChunk cleanup (#19795)
# Objective - Make follow-up changes from #18866 ## Solution - Switch from the on add observer to an on insert hook - Make the component immutable - Remove required components ## Testing - `tilemap_chunk` example
1 parent a3d406d commit 04c2b32

File tree

2 files changed

+50
-45
lines changed

2 files changed

+50
-45
lines changed

crates/bevy_sprite/src/tilemap_chunk/mod.rs

Lines changed: 50 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ use bevy_derive::{Deref, DerefMut};
55
use bevy_ecs::{
66
component::Component,
77
entity::Entity,
8-
lifecycle::Add,
9-
observer::On,
8+
lifecycle::HookContext,
109
query::Changed,
1110
resource::Resource,
12-
system::{Commands, Query, ResMut},
11+
system::{Query, ResMut},
12+
world::DeferredWorld,
1313
};
1414
use bevy_image::{Image, ImageSampler};
1515
use bevy_math::{FloatOrd, UVec2, Vec2, Vec3};
@@ -33,7 +33,6 @@ pub struct TilemapChunkPlugin;
3333
impl Plugin for TilemapChunkPlugin {
3434
fn build(&self, app: &mut App) {
3535
app.init_resource::<TilemapChunkMeshCache>()
36-
.add_observer(on_add_tilemap_chunk)
3736
.add_systems(Update, update_tilemap_chunk_indices);
3837
}
3938
}
@@ -47,7 +46,8 @@ pub struct TilemapChunkMeshCache(HashMap<TilemapChunkMeshCacheKey, Handle<Mesh>>
4746
/// A component representing a chunk of a tilemap.
4847
/// Each chunk is a rectangular section of tiles that is rendered as a single mesh.
4948
#[derive(Component, Clone, Debug, Default)]
50-
#[require(Mesh2d, MeshMaterial2d<TilemapChunkMaterial>, TilemapChunkIndices, Anchor)]
49+
#[require(Anchor)]
50+
#[component(immutable, on_insert = on_insert_tilemap_chunk)]
5151
pub struct TilemapChunk {
5252
/// The size of the chunk in tiles
5353
pub chunk_size: UVec2,
@@ -62,70 +62,75 @@ pub struct TilemapChunk {
6262

6363
/// Component storing the indices of tiles within a chunk.
6464
/// Each index corresponds to a specific tile in the tileset.
65-
#[derive(Component, Clone, Debug, Default, Deref, DerefMut)]
65+
#[derive(Component, Clone, Debug, Deref, DerefMut)]
6666
pub struct TilemapChunkIndices(pub Vec<Option<u16>>);
6767

68-
fn on_add_tilemap_chunk(
69-
trigger: On<Add, TilemapChunk>,
70-
tilemap_chunk_query: Query<(&TilemapChunk, &TilemapChunkIndices, &Anchor)>,
71-
mut commands: Commands,
72-
mut meshes: ResMut<Assets<Mesh>>,
73-
mut materials: ResMut<Assets<TilemapChunkMaterial>>,
74-
mut images: ResMut<Assets<Image>>,
75-
mut tilemap_chunk_mesh_cache: ResMut<TilemapChunkMeshCache>,
76-
) {
77-
let chunk_entity = trigger.target();
78-
let Ok((
79-
TilemapChunk {
80-
chunk_size,
81-
tile_display_size,
82-
tileset,
83-
alpha_mode,
84-
},
85-
indices,
86-
anchor,
87-
)) = tilemap_chunk_query.get(chunk_entity)
88-
else {
89-
warn!("Tilemap chunk {} not found", chunk_entity);
68+
fn on_insert_tilemap_chunk(mut world: DeferredWorld, HookContext { entity, .. }: HookContext) {
69+
let Some(tilemap_chunk) = world.get::<TilemapChunk>(entity) else {
70+
warn!("TilemapChunk not found for tilemap chunk {}", entity);
71+
return;
72+
};
73+
74+
let chunk_size = tilemap_chunk.chunk_size;
75+
let alpha_mode = tilemap_chunk.alpha_mode;
76+
let tileset = tilemap_chunk.tileset.clone();
77+
78+
let Some(indices) = world.get::<TilemapChunkIndices>(entity) else {
79+
warn!("TilemapChunkIndices not found for tilemap chunk {}", entity);
80+
return;
81+
};
82+
83+
let Some(&anchor) = world.get::<Anchor>(entity) else {
84+
warn!("Anchor not found for tilemap chunk {}", entity);
9085
return;
9186
};
9287

9388
let expected_indices_length = chunk_size.element_product() as usize;
9489
if indices.len() != expected_indices_length {
9590
warn!(
9691
"Invalid indices length for tilemap chunk {} of size {}. Expected {}, got {}",
97-
chunk_entity,
92+
entity,
9893
chunk_size,
9994
indices.len(),
10095
expected_indices_length
10196
);
10297
return;
10398
}
10499

105-
let indices_image = make_chunk_image(chunk_size, &indices.0);
100+
let indices_image = make_chunk_image(&chunk_size, &indices.0);
106101

107-
let display_size = (chunk_size * tile_display_size).as_vec2();
102+
let display_size = (chunk_size * tilemap_chunk.tile_display_size).as_vec2();
108103

109104
let mesh_key: TilemapChunkMeshCacheKey = (
110-
*chunk_size,
105+
chunk_size,
111106
FloatOrd(display_size.x),
112107
FloatOrd(display_size.y),
113108
FloatOrd(anchor.as_vec().x),
114109
FloatOrd(anchor.as_vec().y),
115110
);
116111

117-
let mesh = tilemap_chunk_mesh_cache
118-
.entry(mesh_key)
119-
.or_insert_with(|| meshes.add(make_chunk_mesh(chunk_size, &display_size, anchor)));
120-
121-
commands.entity(chunk_entity).insert((
122-
Mesh2d(mesh.clone()),
123-
MeshMaterial2d(materials.add(TilemapChunkMaterial {
124-
tileset: tileset.clone(),
125-
indices: images.add(indices_image),
126-
alpha_mode: *alpha_mode,
127-
})),
128-
));
112+
let tilemap_chunk_mesh_cache = world.resource::<TilemapChunkMeshCache>();
113+
let mesh = if let Some(mesh) = tilemap_chunk_mesh_cache.get(&mesh_key) {
114+
mesh.clone()
115+
} else {
116+
let mut meshes = world.resource_mut::<Assets<Mesh>>();
117+
meshes.add(make_chunk_mesh(&chunk_size, &display_size, &anchor))
118+
};
119+
120+
let mut images = world.resource_mut::<Assets<Image>>();
121+
let indices = images.add(indices_image);
122+
123+
let mut materials = world.resource_mut::<Assets<TilemapChunkMaterial>>();
124+
let material = materials.add(TilemapChunkMaterial {
125+
tileset,
126+
indices,
127+
alpha_mode,
128+
});
129+
130+
world
131+
.commands()
132+
.entity(entity)
133+
.insert((Mesh2d(mesh), MeshMaterial2d(material)));
129134
}
130135

131136
fn update_tilemap_chunk_indices(
@@ -154,6 +159,7 @@ fn update_tilemap_chunk_indices(
154159
continue;
155160
}
156161

162+
// Getting the material mutably to trigger change detection
157163
let Some(material) = materials.get_mut(material.id()) else {
158164
warn!(
159165
"TilemapChunkMaterial not found for tilemap chunk {}",

crates/bevy_sprite/src/tilemap_chunk/tilemap_chunk_material.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use bevy_render::{
99
};
1010

1111
/// Plugin that adds support for tilemap chunk materials.
12-
#[derive(Default)]
1312
pub struct TilemapChunkMaterialPlugin;
1413

1514
impl Plugin for TilemapChunkMaterialPlugin {

0 commit comments

Comments
 (0)