diff options
author | Daniel Schadt <kingdread@gmx.de> | 2019-12-25 01:36:40 +0100 |
---|---|---|
committer | Daniel Schadt <kingdread@gmx.de> | 2019-12-25 01:36:40 +0100 |
commit | 12d00d3cfed39c7bcabd0ded425abf39d402e91b (patch) | |
tree | b885c2859ad33779687e4908eefecfefc35ae1a0 | |
parent | 0f21a84027fd0ab7b55ddca381a7710c93bda6e1 (diff) | |
download | kondou-12d00d3cfed39c7bcabd0ded425abf39d402e91b.tar.gz kondou-12d00d3cfed39c7bcabd0ded425abf39d402e91b.tar.bz2 kondou-12d00d3cfed39c7bcabd0ded425abf39d402e91b.zip |
[render] factor out trait position calculation
Working with a "grid" system where we can specifiy the row and column
number directly is way easier than all the x_slice/y_slice calculations
that have been done in all the methods.
-rw-r--r-- | src/render.rs | 131 |
1 files changed, 96 insertions, 35 deletions
diff --git a/src/render.rs b/src/render.rs index 9341848..d4f9c49 100644 --- a/src/render.rs +++ b/src/render.rs @@ -110,6 +110,7 @@ const TRAITS_PER_TIER: u32 = 3; const TIER_COUNT: u32 = 3; const TOTAL_COLUMN_COUNT: u32 = 2 * TIER_COUNT; const MINOR_LINE_SPLIT: u32 = 4; +const MIDDLE_COL: u32 = 1; fn half<T: Num>(input: T) -> T { let two = T::one() + T::one(); @@ -121,6 +122,7 @@ pub struct Renderer<'r> { options: RenderOptions, minor_mask: DynamicImage, major_mask: DynamicImage, + grid: Grid, } impl<'r> Renderer<'r> { @@ -132,11 +134,19 @@ impl<'r> Renderer<'r> { let major_mask = image::load_from_memory(include_bytes!("major_trait_mask.png")) .expect("Major mask image could not be loaded") .resize(options.trait_size, options.trait_size, CatmullRom); + let grid = Grid { + x_offset: options.traitline_x_offset, + width: options.traitline_width - options.traitline_x_offset, + height: options.traitline_height, + rows: TRAITS_PER_TIER, + cols: TOTAL_COLUMN_COUNT, + }; Renderer { api, options, minor_mask, major_mask, + grid, } } @@ -164,18 +174,22 @@ impl<'r> Renderer<'r> { buffer: &mut RgbaImage, minor: &Trait, ) -> Result<(), RenderError> { - let minor_img = self.api.get_image(&minor.icon)?.resize( - self.options.trait_size, - self.options.trait_size, - CatmullRom, - ); + let trait_size = self.options.trait_size; + let minor_img = self + .api + .get_image(&minor.icon)? + .resize(trait_size, trait_size, CatmullRom); let minor_img = with_mask(&minor_img, &self.minor_mask); - let y_pos = half(buffer.height() - minor_img.height()); - let x_slice = (buffer.width() - self.options.traitline_x_offset) / TOTAL_COLUMN_COUNT; - let x_pos = 2 * (minor.tier - 1) * x_slice - + half(x_slice - minor_img.width()) - + self.options.traitline_x_offset; - imageops::overlay(buffer, &minor_img, x_pos, y_pos); + // Minor traits are always in the middle row, which should be 1. + // We also need to skip the major columns, therefore we need to multiply the column number + // by two. + let (x, y) = self.grid.pos(MIDDLE_COL, 2 * (minor.tier - 1)); + imageops::overlay( + buffer, + &minor_img, + x - half(trait_size), + y - half(trait_size), + ); Ok(()) } @@ -186,25 +200,24 @@ impl<'r> Renderer<'r> { vertical_pos: u8, chosen: bool, ) -> Result<(), RenderError> { - let major_img = self.api.get_image(&major.icon)?.resize( - self.options.trait_size, - self.options.trait_size, - CatmullRom, - ); + let trait_size = self.options.trait_size; + let major_img = self + .api + .get_image(&major.icon)? + .resize(trait_size, trait_size, CatmullRom); let major_img = if !chosen { with_mask(&major_img.grayscale(), &major_img) } else { major_img.to_rgba() }; let major_img = with_mask(&major_img, &self.major_mask); - let y_slice = buffer.height() / TRAITS_PER_TIER; - let y_pos = vertical_pos as u32 * y_slice + half(y_slice - major_img.height()); - let x_slice = (buffer.width() - self.options.traitline_x_offset) / TOTAL_COLUMN_COUNT; - let x_pos = 2 * (major.tier - 1) * x_slice - + x_slice - + half(x_slice - major_img.width()) - + self.options.traitline_x_offset; - imageops::overlay(buffer, &major_img, x_pos, y_pos); + let (x, y) = self.grid.pos(vertical_pos as u32, 2 * (major.tier - 1) + 1); + imageops::overlay( + buffer, + &major_img, + x - half(trait_size), + y - half(trait_size), + ); Ok(()) } @@ -218,15 +231,13 @@ impl<'r> Renderer<'r> { return Ok(()); } - let x_slice = (buffer.width() - self.options.traitline_x_offset) / TOTAL_COLUMN_COUNT; - let start_x = 2 * tier as u32 * x_slice - + half(x_slice + self.options.trait_size) - + self.options.traitline_x_offset; - let end_x = start_x + x_slice - self.options.trait_size; - let start_y = half(buffer.height() - self.options.trait_size) - + self.options.trait_size / MINOR_LINE_SPLIT * (choice as u32); - let y_slice = buffer.height() / TRAITS_PER_TIER; - let end_y = y_slice * (choice as u32 - 1) + half(y_slice); + let trait_size = self.options.trait_size; + let (start_x, start_y) = self.grid.pos(MIDDLE_COL, 2 * tier as u32); + let start_x = start_x + half(trait_size); + let start_y = start_y - half(trait_size) + trait_size / MINOR_LINE_SPLIT * (choice as u32); + + let (end_x, end_y) = self.grid.pos(choice as u32 - 1, 2 * tier as u32 + 1); + let end_x = end_x - half(trait_size); draw_thick_line( buffer, @@ -241,8 +252,8 @@ impl<'r> Renderer<'r> { draw_thick_line( buffer, - (end_x + self.options.trait_size, end_y), - (end_x + x_slice, start_y), + (end_x + trait_size, end_y), + (end_x + self.grid.x_slice(), start_y), self.options.line_height, self.options.line_color, ); @@ -485,3 +496,53 @@ fn draw_thick_line<I>( half_y - half(line_length), ); } + +/// A helper structure representing a grid of squares. +/// +/// This can be used to calculate the centers of the traits that should be placed on the +/// traitlines. +struct Grid { + x_offset: u32, + width: u32, + height: u32, + rows: u32, + cols: u32, +} + +impl Grid { + /// Return the coordinates of the center of the given square. + #[inline(always)] + fn pos(&self, row: u32, col: u32) -> (u32, u32) { + assert!( + row < self.rows, + "row {} is outside the bounds ({})", + row, + self.rows + ); + assert!( + col < self.cols, + "col {} is outside the bounds ({})", + col, + self.cols + ); + + let x_slice = self.x_slice(); + let y_slice = self.y_slice(); + + let x_pos = x_slice * col + self.x_offset + half(x_slice); + let y_pos = y_slice * row + half(y_slice); + (x_pos, y_pos) + } + + /// Returns the width of a x slice. + #[inline(always)] + fn x_slice(&self) -> u32 { + self.width / self.cols + } + + /// Returns the height of an y slice. + #[inline(always)] + fn y_slice(&self) -> u32 { + self.height / self.rows + } +} |