aboutsummaryrefslogtreecommitdiff
path: root/renderer/src/map.rs
diff options
context:
space:
mode:
Diffstat (limited to 'renderer/src/map.rs')
-rw-r--r--renderer/src/map.rs163
1 files changed, 163 insertions, 0 deletions
diff --git a/renderer/src/map.rs b/renderer/src/map.rs
new file mode 100644
index 0000000..0ea3a6b
--- /dev/null
+++ b/renderer/src/map.rs
@@ -0,0 +1,163 @@
+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<Option<usize>, 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<u8> = 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;
+ }
+
+ for layer_y in (center.1 - 30)..(center.1 + 30) {
+ for layer_x in (center.0 - 30)..(center.0 + 30) {
+ let layer_x = layer_x.try_into().unwrap_or(0);
+ let layer_y = layer_y.try_into().unwrap_or(0);
+
+ if layer_x >= l.tiles.dim().1 || layer_y >= l.tiles.dim().0 {
+ continue;
+ }
+ let tile = l.tiles[(layer_y, layer_x)];
+
+ 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;
+ }
+
+ 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);
+
+ 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,
+ // );
+ // }
+ // }
+ }
+ }
+ }
+ }
+}