fix a couple bugs which could cause chunks to get eaten away across reloads

mainly related to me not knowing how to decode WebP properly (I blame the API design of the webp crate)
turns out it can return RGB images instead of RGBA and so you have to convert it to RGBA first

there were also a couple math bugs with chunk drawing/saving related to some of my refactors of that math
This commit is contained in:
liquidex 2024-08-24 17:18:44 +02:00
parent c55f5e054c
commit fb0e15c00c
3 changed files with 26 additions and 7 deletions

View file

@ -21,7 +21,7 @@ use tokio::{
select, select,
sync::{mpsc, oneshot}, sync::{mpsc, oneshot},
}; };
use tracing::{error, instrument}; use tracing::{error, info, instrument};
use crate::{ use crate::{
haku::{Haku, Limits}, haku::{Haku, Limits},
@ -450,7 +450,7 @@ fn chunks_to_modify(wall: &Wall, points: &[Vec2]) -> HashSet<ChunkPosition> {
let top_left_chunk = wall.settings().chunk_at(Vec2::new(left, top)); let top_left_chunk = wall.settings().chunk_at(Vec2::new(left, top));
let bottom_right_chunk = wall let bottom_right_chunk = wall
.settings() .settings()
.chunk_at(Vec2::new(left + paint_area, top + paint_area)); .chunk_at_ceil(Vec2::new(left + paint_area, top + paint_area));
for chunk_y in top_left_chunk.y..bottom_right_chunk.y { for chunk_y in top_left_chunk.y..bottom_right_chunk.y {
for chunk_x in top_left_chunk.x..bottom_right_chunk.x { for chunk_x in top_left_chunk.x..bottom_right_chunk.x {
chunks.insert(ChunkPosition::new(chunk_x, chunk_y)); chunks.insert(ChunkPosition::new(chunk_x, chunk_y));
@ -472,8 +472,8 @@ fn draw_to_chunks(wall: &Wall, haku: &Haku, value: Value, center: Vec2) -> eyre:
let left_chunk = settings.chunk_at_1d(left); let left_chunk = settings.chunk_at_1d(left);
let top_chunk = settings.chunk_at_1d(top); let top_chunk = settings.chunk_at_1d(top);
let right_chunk = settings.chunk_at_1d(left + paint_area); let right_chunk = settings.chunk_at_1d_ceil(left + paint_area);
let bottom_chunk = settings.chunk_at_1d(top + paint_area); let bottom_chunk = settings.chunk_at_1d_ceil(top + paint_area);
for chunk_y in top_chunk..bottom_chunk { for chunk_y in top_chunk..bottom_chunk {
for chunk_x in left_chunk..right_chunk { for chunk_x in left_chunk..right_chunk {
let x = f32::floor(-chunk_x as f32 * chunk_size + center.x); let x = f32::floor(-chunk_x as f32 * chunk_size + center.x);

View file

@ -128,9 +128,20 @@ impl Settings {
f32::floor(x / self.chunk_size as f32) as i32 f32::floor(x / self.chunk_size as f32) as i32
} }
pub fn chunk_at_1d_ceil(&self, x: f32) -> i32 {
f32::ceil(x / self.chunk_size as f32) as i32
}
pub fn chunk_at(&self, position: Vec2) -> ChunkPosition { pub fn chunk_at(&self, position: Vec2) -> ChunkPosition {
ChunkPosition::new(self.chunk_at_1d(position.x), self.chunk_at_1d(position.y)) ChunkPosition::new(self.chunk_at_1d(position.x), self.chunk_at_1d(position.y))
} }
pub fn chunk_at_ceil(&self, position: Vec2) -> ChunkPosition {
ChunkPosition::new(
self.chunk_at_1d_ceil(position.x),
self.chunk_at_1d_ceil(position.y),
)
}
} }
pub struct Wall { pub struct Wall {

View file

@ -160,7 +160,14 @@ impl ChunkImageLoop {
webp::Decoder::new(data) webp::Decoder::new(data)
.decode() .decode()
.and_then(|image| { .and_then(|image| {
info!(?position, "decoded"); info!(
?position,
width = image.width(),
height = image.height(),
data_len = image.len(),
"decoded"
);
let image = image.to_image().into_rgba8();
let size = IntSize::from_wh(image.width(), image.height())?; let size = IntSize::from_wh(image.width(), image.height())?;
Pixmap::from_vec(image.to_vec(), size) Pixmap::from_vec(image.to_vec(), size)
}) })
@ -173,15 +180,16 @@ impl ChunkImageLoop {
// I don't know yet if locking all the chunks is a good idea at this point. // I don't know yet if locking all the chunks is a good idea at this point.
// I can imagine contended chunks having some trouble loading. // I can imagine contended chunks having some trouble loading.
let chunk_arcs: Vec<_> = chunks let chunk_arcs: Vec<_> = decoded
.iter() .iter()
.map(|ChunkDataPair { position, .. }| self.wall.get_or_create_chunk(*position)) .map(|(position, _)| self.wall.get_or_create_chunk(*position))
.collect(); .collect();
let mut chunk_refs = Vec::with_capacity(chunk_arcs.len()); let mut chunk_refs = Vec::with_capacity(chunk_arcs.len());
for arc in &chunk_arcs { for arc in &chunk_arcs {
chunk_refs.push(arc.lock().await); chunk_refs.push(arc.lock().await);
} }
info!(num = ?chunk_refs.len(), "replacing chunks' pixmaps");
for ((_, pixmap), mut chunk) in decoded.into_iter().zip(chunk_refs) { for ((_, pixmap), mut chunk) in decoded.into_iter().zip(chunk_refs) {
chunk.pixmap = pixmap; chunk.pixmap = pixmap;
} }