aboutsummaryrefslogtreecommitdiff
path: root/src/infinite_grid.rs
blob: 163c2b2745db71d7f1b12fd496b2fc7bcca56441 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//! Grid that can be moved and scaled, and which gives the appearance of being infinite, while
//! staying easily renderable.

use crate::transform::Transform;
use piston_window::grid::Grid;
use piston_window::line::{Line, Shape};
use piston_window::{Context, Graphics, Size, Transformed};

/// The line used to draw the grids lines
const GRID_LINE: Line = Line {
    color: [1., 1., 1., 0.3],
    radius: 1.2,
    shape: Shape::Square,
};

pub struct InfiniteGrid(Grid);

impl InfiniteGrid {
    pub fn new(transform: &Transform, draw_size: Size) -> InfiniteGrid {
        /* Create a grid with two extra columns and rows per draw_size, so when the user moves the
         * grid up and down they can be seen, before the grid position is reset to create the
         * infinitness illusion.
         * The +3 instead of the +2 is necessary, since the amount needed may be underestimated
         * because of rounding errors (I think)
         */
        InfiniteGrid(Grid {
            cols: (draw_size.width / transform.pixels_per_m()) as u32 + 3,
            rows: (draw_size.height / transform.pixels_per_m()) as u32 + 3,
            units: transform.pixels_per_m(),
        })
    }

    // TODO: Yes, this is ugly af
    pub fn on_scale_change(&mut self, transform: &Transform, draw_size: Size) {
        self.0.cols = (draw_size.width / transform.pixels_per_m()) as u32 + 3;
        self.0.rows = (draw_size.height / transform.pixels_per_m()) as u32 + 3;
        self.0.units = transform.pixels_per_m()
    }

    pub fn draw<G>(&self, map_trans: &Transform, context: &Context, g: &mut G)
    where
        G: Graphics,
    {
        /* Since mouse movement is actually always provided as whole pixels, this is fine.
         * the - cell_size (i.e. pixels_per_m) is provided, so that the grid is centered in the
         * screen,and not at position 0.x, 0.x, which would mean there would be no row at the top
         * and/or no column to the left.
         */
        let actual_trans_px = [
            (map_trans.translation_px()[0] as i64 % self.0.units as i64) as f64
                - map_trans.pixels_per_m(),
            (map_trans.translation_px()[1] as i64 % self.0.units as i64) as f64
                - map_trans.pixels_per_m(),
        ];

        self.0.draw(
            &GRID_LINE,
            &context.draw_state,
            context.trans_pos(actual_trans_px).transform,
            g,
        );
    }
}