fix: correct boundary z-marking and tileset_index swap in recolor
Boundary: mark all z-levels where z_diff changed, not just 4 boundary indices. For multi-step scrolls, every z-level between min(old,new)-8 and max(old,new) inclusive needs recoloring. Also fixes last_z_change_dirty_count to use actual new_keys.len(). Recolor: update tileset_index alongside color so sky tile switch at t>=0.98 actually renders the sky texture, not sky-coloured grass. Cleanup: removed solid_bits (was unused after recolor fix).
This commit is contained in:
@@ -39,7 +39,6 @@ impl Default for TilemapChunkRegistry {
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct TilemapChunkStates {
|
||||
pub solid_bits: HashMap<ChunkLayerKey, u64>,
|
||||
pub underground_bits: HashMap<ChunkLayerKey, u64>,
|
||||
}
|
||||
|
||||
@@ -203,17 +202,18 @@ fn populate_chunk_tiles(
|
||||
fn recolor_chunk_for_depth(
|
||||
tile_data: &mut TilemapChunkTileData,
|
||||
z_diff: i32,
|
||||
solid_bits: u64,
|
||||
underground_bits: u64,
|
||||
) {
|
||||
for (i, slot) in tile_data.0.iter_mut().enumerate() {
|
||||
let Some(td) = slot else { continue };
|
||||
let is_underground = (underground_bits >> i) & 1 == 1;
|
||||
td.color = if is_underground {
|
||||
Color::BLACK
|
||||
if is_underground {
|
||||
td.color = Color::BLACK;
|
||||
} else {
|
||||
tile_fade_color(td.tileset_index, z_diff)
|
||||
};
|
||||
let recomputed = tile_for_depth(td.tileset_index, z_diff);
|
||||
td.tileset_index = recomputed.tileset_index;
|
||||
td.color = recomputed.color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +250,6 @@ pub fn spawn_tilemap_chunks(
|
||||
registry.entities.clear();
|
||||
registry.dirty_keys.clear();
|
||||
registry.z_change_keys.clear();
|
||||
states.solid_bits.clear();
|
||||
states.underground_bits.clear();
|
||||
spawner.started = true;
|
||||
}
|
||||
@@ -269,8 +268,6 @@ pub fn spawn_tilemap_chunks(
|
||||
|
||||
let (tile_data, underground_bits) = if key.layer == LAYER_FLOOR {
|
||||
let (tiles, ub) = populate_chunk_tiles(&tilemap, key.chunk_pos, key.z_index, camera_z);
|
||||
let solid_bits = compute_solid_bits(&tiles);
|
||||
states.solid_bits.insert(key, solid_bits);
|
||||
states.underground_bits.insert(key, ub);
|
||||
(tiles, ub)
|
||||
} else {
|
||||
@@ -317,18 +314,6 @@ pub fn spawn_tilemap_chunks(
|
||||
bench.populate_ms += now.elapsed().as_secs_f64() * 1000.0;
|
||||
}
|
||||
|
||||
fn compute_solid_bits(tiles: &[Option<TileData>]) -> u64 {
|
||||
let mut bits: u64 = 0;
|
||||
for (i, slot) in tiles.iter().enumerate() {
|
||||
if let Some(td) = slot {
|
||||
if td.tileset_index != 0 {
|
||||
bits |= 1u64 << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
bits
|
||||
}
|
||||
|
||||
pub fn update_tilemap_chunk_visibility(
|
||||
z_index: Res<ZIndex>,
|
||||
mut query: Query<(&ChunkLayerKey, &mut Visibility)>,
|
||||
@@ -390,9 +375,8 @@ pub fn populate_tilemap_chunk_data(
|
||||
continue;
|
||||
}
|
||||
|
||||
let solid_bits = states.solid_bits.get(&key).copied().unwrap_or(0);
|
||||
let underground_bits = states.underground_bits.get(&key).copied().unwrap_or(0);
|
||||
recolor_chunk_for_depth(&mut tile_data, z_diff, solid_bits, underground_bits);
|
||||
recolor_chunk_for_depth(&mut tile_data, z_diff, underground_bits);
|
||||
processed += 1;
|
||||
}
|
||||
|
||||
@@ -432,8 +416,6 @@ pub fn populate_tilemap_chunk_data(
|
||||
|
||||
let (new_tiles, underground_bits) =
|
||||
populate_chunk_tiles(&tilemap, key.chunk_pos, key.z_index, camera_z);
|
||||
let solid_bits = compute_solid_bits(&new_tiles);
|
||||
states.solid_bits.insert(key, solid_bits);
|
||||
states.underground_bits.insert(key, underground_bits);
|
||||
tile_data.0 = new_tiles;
|
||||
processed += 1;
|
||||
@@ -465,37 +447,28 @@ pub fn on_camera_z_changed(
|
||||
|
||||
let now = Instant::now();
|
||||
|
||||
let old_entered_idx = (old_camera_z as f32 + Z_BELOW) as usize;
|
||||
let old_exited_idx = ((old_camera_z - 8) as f32 + Z_BELOW) as usize;
|
||||
let new_entered_idx = (new_camera_z as f32 + Z_BELOW) as usize;
|
||||
let new_exited_idx = ((new_camera_z - 8) as f32 + Z_BELOW) as usize;
|
||||
|
||||
let mut count = 0;
|
||||
let z_min = (new_camera_z.min(old_camera_z) - 8).max(0);
|
||||
let z_max = new_camera_z.max(old_camera_z);
|
||||
|
||||
let mut new_keys: Vec<ChunkLayerKey> = Vec::new();
|
||||
|
||||
for key in registry.entities.keys() {
|
||||
if key.z_index == old_entered_idx
|
||||
|| key.z_index == new_entered_idx
|
||||
|| key.z_index == old_exited_idx
|
||||
|| key.z_index == new_exited_idx
|
||||
{
|
||||
let tile_z = camera_z_for_z_index(key.z_index);
|
||||
if tile_z >= z_min && tile_z <= z_max {
|
||||
new_keys.push(*key);
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
bench.last_z_change_dirty_ms = now.elapsed().as_secs_f64() * 1000.0;
|
||||
bench.last_z_change_dirty_count = new_keys.len();
|
||||
|
||||
if !new_keys.is_empty() {
|
||||
registry.z_change_keys.clear();
|
||||
for key in new_keys {
|
||||
registry.z_change_keys.insert(key);
|
||||
}
|
||||
}
|
||||
|
||||
bench.last_z_change_dirty_ms = now.elapsed().as_secs_f64() * 1000.0;
|
||||
bench.last_z_change_dirty_count = count;
|
||||
}
|
||||
|
||||
pub fn despawn_tilemap_chunks(
|
||||
mut commands: Commands,
|
||||
chunk_map: Res<super::super::chunks::ChunkMap>,
|
||||
@@ -511,7 +484,6 @@ pub fn despawn_tilemap_chunks(
|
||||
registry.entities.remove(key);
|
||||
registry.dirty_keys.remove(key);
|
||||
registry.z_change_keys.remove(key);
|
||||
states.solid_bits.remove(key);
|
||||
states.underground_bits.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user