Skip to content

Commit

Permalink
Fix rendering of event graphics and the tilepicker (#36)
Browse files Browse the repository at this point in the history
* Implement `calc_quad` in atlas.rs properly

This is just a stopgap to get the events with tileset graphics rendering
properly.

It's probably better to get rendering of these events to go through the
tilemap shader somehow...

* Move the "+ 1" from atlas.rs to event.rs in case it is an isolated issue

* Implement `Tiles::draw` for the tilepicker and other non-layered surfaces

* Run rustfmt on src/graphics/primitives/tiles/mod.rs

* Tilepicker no longer needs to clone or copy the atlas

* Atlas wraparound is now handled when rendering tiles
  • Loading branch information
white-axe authored Sep 11, 2023
1 parent 29833bf commit 8d2fc69
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 23 deletions.
19 changes: 7 additions & 12 deletions src/components/tilepicker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -51,8 +50,8 @@ impl Tilepicker {
pub fn new(tileset: &rpg::Tileset) -> Result<Tilepicker, String> {
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(
Expand All @@ -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,
Expand All @@ -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(),
})
Expand All @@ -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(),
);

Expand All @@ -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];
Expand All @@ -122,7 +117,7 @@ impl Tilepicker {
} = resources.as_ref();

viewport.bind(render_pass);
tiles.draw(render_pass, &[]);
tiles.draw(render_pass, None);
}),
),
});
Expand Down
3 changes: 2 additions & 1 deletion src/graphics/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.));

Expand Down
2 changes: 1 addition & 1 deletion src/graphics/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
51 changes: 49 additions & 2 deletions src/graphics/primitives/tiles/atlas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!

Expand Down Expand Up @@ -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,
)
}
Expand Down
9 changes: 7 additions & 2 deletions src/graphics/primitives/tiles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
30 changes: 25 additions & 5 deletions src/graphics/primitives/tiles/tilemap.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,31 @@ fn vs_main(vertex: VertexInput, instance: InstanceInput) -> VertexOutput {
let position = viewport.proj * vec4<f32>(vertex.position.xy + (instance.tile_position.xy * 32.), 0.0, 1.0);
out.clip_position = vec4<f32>(position.xy, instance.tile_position.z, 1.0);

var atlas_tile_position = vec2<f32>(
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<f32>( // 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<f32>( // 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<f32>( // 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);
Expand All @@ -69,4 +89,4 @@ fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
}

return color;
}
}

0 comments on commit 8d2fc69

Please sign in to comment.