diff --git a/src/components/tilepicker.rs b/src/components/tilepicker.rs index 4611aa87..2878ed84 100644 --- a/src/components/tilepicker.rs +++ b/src/components/tilepicker.rs @@ -31,7 +31,6 @@ pub struct Tilepicker { struct Resources { tiles: primitives::Tiles, viewport: primitives::Viewport, - atlas: primitives::Atlas, } #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] @@ -51,8 +50,8 @@ impl Tilepicker { pub fn new(tileset: &rpg::Tileset) -> Result { let atlas = state!().atlas_cache.load_atlas(tileset)?; - let tilepicker_data = [0, 48, 96, 144, 192, 240, 288, 336] - .into_iter() + let tilepicker_data = (0..384) + .step_by(48) .chain(384..(atlas.tileset_height as i16 / 32 * 8 + 384)) .collect_vec(); let tilepicker_data = Table3::new_data( @@ -61,7 +60,6 @@ impl Tilepicker { 1, tilepicker_data, ); - let tiles = primitives::Tiles::new(atlas.clone(), &tilepicker_data); let viewport = primitives::Viewport::new(cgmath::ortho( 0.0, @@ -72,12 +70,10 @@ impl Tilepicker { 1.0, )); + let tiles = primitives::Tiles::new(atlas, &tilepicker_data); + Ok(Self { - resources: Arc::new(Resources { - tiles, - viewport, - atlas, - }), + resources: Arc::new(Resources { tiles, viewport }), ani_instant: Instant::now(), selected_tile: SelectedTile::default(), }) @@ -91,7 +87,7 @@ impl Tilepicker { ui.ctx().request_repaint_after(Duration::from_millis(16)); let (canvas_rect, response) = ui.allocate_exact_size( - egui::vec2(256., self.resources.atlas.tileset_height as f32), + egui::vec2(256., self.resources.tiles.atlas.tileset_height as f32), egui::Sense::click_and_drag(), ); @@ -113,7 +109,6 @@ impl Tilepicker { vec![] }) .paint(move |_info, render_pass, paint_callback_resources| { - // let res_hash: &ResourcesSlab = paint_callback_resources.get().unwrap(); let id = paint_id.get().copied().expect("resources id is unset"); let resources = &res_hash[id]; @@ -122,7 +117,7 @@ impl Tilepicker { } = resources.as_ref(); viewport.bind(render_pass); - tiles.draw(render_pass, &[]); + tiles.draw(render_pass, None); }), ), }); diff --git a/src/graphics/event.rs b/src/graphics/event.rs index aa2e8160..839d29fc 100644 --- a/src/graphics/event.rs +++ b/src/graphics/event.rs @@ -49,7 +49,8 @@ impl Event { }; let (quads, viewport, sprite_size) = if let Some(id) = page.graphic.tile_id { - let quad = atlas.calc_quad(id as i16, event.x as usize, event.y as usize); + // Why does this have to be + 1? + let quad = atlas.calc_quad((id + 1) as i16, event.x as usize, event.y as usize); let viewport = primitives::Viewport::new(cgmath::ortho(0.0, 32., 32., 0., -1., 1.)); diff --git a/src/graphics/map.rs b/src/graphics/map.rs index d218e734..530cc4ea 100644 --- a/src/graphics/map.rs +++ b/src/graphics/map.rs @@ -149,7 +149,7 @@ impl Map { } } - tiles.draw(render_pass, &enabled_layers); + tiles.draw(render_pass, Some(&enabled_layers)); if fog_enabled { if let Some(fog) = fog { fog.draw(render_pass); diff --git a/src/graphics/primitives/tiles/atlas.rs b/src/graphics/primitives/tiles/atlas.rs index ebdb6da4..ddfb1ce0 100644 --- a/src/graphics/primitives/tiles/atlas.rs +++ b/src/graphics/primitives/tiles/atlas.rs @@ -26,11 +26,15 @@ pub const TILESET_WIDTH: u32 = TILE_SIZE * TILESET_COLUMNS; // self explanatory pub const AUTOTILE_ID_AMOUNT: u32 = 48; // there are 48 tile ids per autotile pub const AUTOTILE_FRAME_COLS: u32 = TILESET_COLUMNS; // this is how many "columns" of autotiles there are per frame pub const AUTOTILE_AMOUNT: u32 = 7; // There are 7 autotiles per tileset +pub const TOTAL_AUTOTILE_ID_AMOUNT: u32 = AUTOTILE_ID_AMOUNT * (AUTOTILE_AMOUNT + 1); // the first 384 tile ids are for autotiles (including empty tiles) pub const AUTOTILE_ROWS: u32 = AUTOTILE_ID_AMOUNT / AUTOTILE_FRAME_COLS; // split up the 48 tiles across each tileset row +pub const TOTAL_AUTOTILE_ROWS: u32 = AUTOTILE_ROWS * AUTOTILE_AMOUNT; // total number of rows for all autotiles combined pub const AUTOTILE_ROW_HEIGHT: u32 = AUTOTILE_ROWS * TILE_SIZE; // This is how high one row of autotiles is pub const TOTAL_AUTOTILE_HEIGHT: u32 = AUTOTILE_ROW_HEIGHT * AUTOTILE_AMOUNT; // self explanatory pub const HEIGHT_UNDER_AUTOTILES: u32 = MAX_SIZE - TOTAL_AUTOTILE_HEIGHT; // this is the height under autotiles +pub const ROWS_UNDER_AUTOTILES: u32 = MAX_SIZE / TILE_SIZE - TOTAL_AUTOTILE_ROWS; // number of rows under autotiles +pub const ROWS_UNDER_AUTOTILES_TIMES_COLUMNS: u32 = ROWS_UNDER_AUTOTILES * TILESET_COLUMNS; pub const AUTOTILE_FRAME_WIDTH: u32 = AUTOTILE_FRAME_COLS * TILE_SIZE; // This is per frame! @@ -244,9 +248,52 @@ impl Atlas { } pub fn calc_quad(&self, tile: i16, x: usize, y: usize) -> Quad { + let tile_u32 = if tile < 0 { 0 } else { tile as u32 }; + + let is_autotile = tile_u32 < TOTAL_AUTOTILE_ID_AMOUNT; + let max_frame_count = self.autotile_width / AUTOTILE_FRAME_WIDTH; + let max_tiles_under_autotiles = max_frame_count * ROWS_UNDER_AUTOTILES_TIMES_COLUMNS; + let is_under_autotiles = !is_autotile && tile_u32 - 384 < max_tiles_under_autotiles; + + let atlas_tile_position = if tile_u32 < AUTOTILE_ID_AMOUNT { + egui::pos2(0., 0.) + } else if is_autotile { + egui::pos2( + ((tile_u32 - AUTOTILE_ID_AMOUNT) % AUTOTILE_FRAME_COLS * TILE_SIZE) as f32, + ((tile_u32 - AUTOTILE_ID_AMOUNT) / AUTOTILE_FRAME_COLS * TILE_SIZE) as f32, + ) + } else if is_under_autotiles { + egui::pos2( + ((tile_u32 % TILESET_COLUMNS + + (tile_u32 - TOTAL_AUTOTILE_ID_AMOUNT) / ROWS_UNDER_AUTOTILES_TIMES_COLUMNS + * TILESET_COLUMNS) + * TILE_SIZE) as f32, + (((tile_u32 - TOTAL_AUTOTILE_ID_AMOUNT) / TILESET_COLUMNS % ROWS_UNDER_AUTOTILES + + TOTAL_AUTOTILE_ROWS) + * 32) as f32, + ) + } else { + egui::pos2( + ((tile_u32 % TILESET_COLUMNS + + ((tile_u32 - max_tiles_under_autotiles) + / (MAX_SIZE / TILE_SIZE * TILESET_COLUMNS) + + max_frame_count) + * TILESET_COLUMNS) + * TILE_SIZE) as f32, + ((tile_u32 - max_tiles_under_autotiles) / TILESET_COLUMNS % (MAX_SIZE / TILE_SIZE) + * TILE_SIZE) as f32, + ) + }; + Quad::new( - egui::Rect::from_min_max(egui::pos2(0., 0.), egui::pos2(32., 32.0)), - egui::Rect::from_min_max(egui::pos2(0., 0.), egui::pos2(32., 32.0)), + egui::Rect::from_min_size( + egui::pos2(0., 0.), + egui::vec2(TILE_SIZE as f32, TILE_SIZE as f32), + ), + egui::Rect::from_min_size( + atlas_tile_position, + egui::vec2(TILE_SIZE as f32, TILE_SIZE as f32), + ), 0.0, ) } diff --git a/src/graphics/primitives/tiles/mod.rs b/src/graphics/primitives/tiles/mod.rs index c17f418b..43c99166 100644 --- a/src/graphics/primitives/tiles/mod.rs +++ b/src/graphics/primitives/tiles/mod.rs @@ -54,13 +54,18 @@ impl Tiles { pub fn draw<'rpass>( &'rpass self, render_pass: &mut wgpu::RenderPass<'rpass>, - enabled_layers: &[bool], + enabled_layers: Option<&[bool]>, ) { render_pass.push_debug_group("tilemap tiles renderer"); Shader::bind(render_pass); self.autotiles.bind(render_pass); self.atlas.bind(render_pass); - for (layer, enabled) in enabled_layers.iter().copied().enumerate() { + for (layer, enabled) in enabled_layers + .unwrap_or(&[true]) + .iter() + .copied() + .enumerate() + { if enabled { self.instances.draw(render_pass, layer); } diff --git a/src/graphics/primitives/tiles/tilemap.wgsl b/src/graphics/primitives/tiles/tilemap.wgsl index 30c223db..f38eadea 100644 --- a/src/graphics/primitives/tiles/tilemap.wgsl +++ b/src/graphics/primitives/tiles/tilemap.wgsl @@ -39,11 +39,31 @@ fn vs_main(vertex: VertexInput, instance: InstanceInput) -> VertexOutput { let position = viewport.proj * vec4(vertex.position.xy + (instance.tile_position.xy * 32.), 0.0, 1.0); out.clip_position = vec4(position.xy, instance.tile_position.z, 1.0); - var atlas_tile_position = vec2( - f32((instance.tile_id - 48) % 8 * 32), - f32((instance.tile_id - 48) / 8 * 32) + let is_autotile = instance.tile_id < 384; + + // 1712 is the number of non-autotile tiles that can fit under the autotiles without wrapping around + let max_tiles_under_autotiles = i32(autotiles.max_frame_count) * 1712; + let is_under_autotiles = !is_autotile && instance.tile_id - 384 < max_tiles_under_autotiles; + + var atlas_tile_position = select( + select( + vec2( // If the tile is not an autotile and is not located underneath the autotiles in the atlas + f32((instance.tile_id % 8 + ((instance.tile_id - max_tiles_under_autotiles) / 2048 + i32(autotiles.max_frame_count)) * 8) * 32), + f32((instance.tile_id - max_tiles_under_autotiles) / 8 % 256 * 32) + ), + vec2( // If the tile is not an autotile but is located underneath the autotiles in the atlas + f32((instance.tile_id % 8 + (instance.tile_id - 384) / 1712 * 8) * 32), + f32(((instance.tile_id - 384) / 8 % 214 + 42) * 32) + ), + is_under_autotiles + ), + vec2( // If the tile is an autotile + f32((instance.tile_id - 48) % 8 * 32), + f32((instance.tile_id - 48) / 8 * 32) + ), + is_autotile ); - if instance.tile_id < 384 { + if is_autotile { let frame_count = autotiles.frame_counts[instance.tile_id / 48 - 1]; let frame = autotiles.animation_index % frame_count; atlas_tile_position.x += f32(frame * 256u); @@ -69,4 +89,4 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4 { } return color; -} \ No newline at end of file +}