use std::collections::HashMap; use log::{info, warn}; use skia_safe::{ canvas::SrcRectConstraint, Canvas, Color4f, ColorSpace, ISize, Image, Paint, Rect, }; use twclient::world::{ map::{format, TILE_NUM}, World, }; pub struct MapRenderer { tileset: HashMap, Image>, } impl MapRenderer { pub fn new() -> Self { Self { tileset: HashMap::new(), } } pub fn tick(&mut self) {} pub fn map_changed(&mut self, world: &World) { self.tileset.clear(); for (key, t) in &world.map.tilesets { let mut bytes: Vec = Vec::with_capacity(t.dim().0 * t.dim().1 * 4); info!("loading tileset: {:?} => {:?}", key, t.dim()); for ((_x, _y), c) in t.indexed_iter() { bytes.push(c.red); bytes.push(c.green); bytes.push(c.blue); bytes.push(c.alpha); } let d = skia_safe::Data::new_copy(&bytes); let v = skia_safe::Image::from_raster_data( &skia_safe::ImageInfo::new( ISize::new(t.dim().0 as i32, t.dim().1 as i32), skia_safe::ColorType::RGBA8888, skia_safe::AlphaType::Opaque, None, ), d, t.dim().0 * 4, ) .unwrap(); self.tileset.insert(*key, v); } } pub fn draw(&mut self, world: &World, canvas: &mut Canvas) { let mut grid_paint = Paint::new( Color4f { a: 1.0, r: 1.0, g: 1.0, b: 1.0, }, &ColorSpace::new_srgb(), ); grid_paint.set_style(skia_safe::PaintStyle::Stroke); grid_paint.set_anti_alias(true); let center = world .local_tee() .map(|t| (t.x / 16, t.y / 16)) .unwrap_or((0, 0)); let tile_rect = Rect { top: center.1 as f32 * 16.0, left: center.0 as f32 * 16.0, bottom: center.1 as f32 * 16.0 + 16.0, right: center.0 as f32 * 16.0 + 16.0, }; canvas.draw_rect(tile_rect, &grid_paint); for l in &world.map.layers { let tileset = match world.map.tilesets.get(&l.image) { Some(t) => t, None => { warn!("missing tileset for {:?}, skipping layer", l.image); continue; } }; if tileset.dim() == (1, 1) { continue; } // println!("{:?} {:?}", center, l.tiles.dim()); for layer_y in (center.1 - 15)..(center.1 + 15) { for layer_x in (center.0 - 15)..(center.0 + 15) { let layer_x = layer_x.try_into().unwrap_or(0); let layer_y = layer_y.try_into().unwrap_or(0); let tile_rect = Rect { top: layer_y as f32 * 16.0, left: layer_x as f32 * 16.0, bottom: layer_y as f32 * 16.0 + 16.0, right: layer_x as f32 * 16.0 + 16.0, }; canvas.draw_rect(tile_rect, &grid_paint); let tile = match l.tiles.get((layer_y, layer_x)) { Some(t) => t, None => continue, }; println!("{:?}", tile); let _rotate = tile.flags & format::TILEFLAG_ROTATE != 0; let _vflip = tile.flags & format::TILEFLAG_VFLIP != 0; let _hflip = tile.flags & format::TILEFLAG_HFLIP != 0; let tile_x = tile.index as u32 % TILE_NUM; let tile_y = tile.index as u32 / TILE_NUM; if tile_x == 0 && tile_y == 0 { continue; } const TL: u32 = 16; canvas.draw_image_rect( self.tileset.get(&l.image).unwrap(), Some(( &Rect { top: (tile_y * TL) as f32, left: (tile_x * TL) as f32, bottom: ((tile_y + 1) * TL) as f32, right: ((tile_x + 1) * TL) as f32, }, SrcRectConstraint::Strict, )), tile_rect, &Paint::default(), ); // for iy in 0..TL { // for ix in 0..TL { // let (x, y) = ((layer_x as u32 * TL + iy), (layer_y as u32 * TL + ix)); // let p_tile = // tileset[((tile_y * TL + iy) as usize, (tile_x * TL + ix) as usize)]; // let mut p = Paint::new( // Color4f { // a: 0.0, // b: 0.0, // g: 0.0, // r: 0.0, // }, // &ColorSpace::new_srgb(), // ); // p.set_argb(p_tile.alpha, p_tile.red, p_tile.green, p_tile.green); // p.set_style(PaintStyle::Fill); // canvas.draw_rect( // Rect { // left: x as f32, // top: y as f32, // right: x as f32 + 1.0, // bottom: y as f32 + 1.0, // }, // &p, // ); // } // } } } } } }