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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
pub mod infinite_grid;
pub mod transform;
use infinite_grid::*;
use transform::*;
use piston_window::grid::Grid;
use piston_window::rectangle::{Border, Rectangle};
use piston_window::*;
use sdl2_window::Sdl2Window;
/// Helper function to turn two given points into a rectangle. The order of the two points is not
/// important, they are considered two endpoints of a diagonal and therefore identify the rectangle
/// unambiguously.
fn bounding_box(p0: [f64; 2], p1: [f64; 2]) -> [f64; 4] {
let min_x = p0[0].min(p1[0]);
let min_y = p0[1].min(p1[1]);
let max_x = p0[0].max(p1[0]);
let max_y = p0[1].max(p1[1]);
[min_x, min_y, max_x - min_x, max_y - min_y]
}
fn main() {
let mut window: PistonWindow<Sdl2Window> = WindowSettings::new("Hello there!", [1000, 1000])
.build()
.expect("Could not initialise window");
// The amount of on-screen pixels used to represent a meter of actual terrain.
let mut transform = Transform::new();
let mut grid = InfiniteGrid::new(&transform, window.draw_size());
/* Create a rectangle that is used to draw all rectangles that were created by the user. It has
* a thicc blacc border and white colour.
*/
let render_rect = Rectangle::new([0.7, 0.7, 0.7, 1.]).border(Border {
color: [0.5, 0.5, 0.5, 1.],
radius: 2.,
});
// The point the user has clicked. This is where they want the rectangle to start.
let mut starting_rect_point: Option<[f64; 2]> = None;
let mut rectangles = Vec::new();
let mut mouse_pos_px = [0., 0.];
let mut mouse_pos_m = [0., 0.];
let mut canvas_follows_mouse = false;
let mut events = Events::new(EventSettings::new().lazy(true));
while let Some(e) = events.next(&mut window) {
// Update the mouse cursor position and possibly the canvas position too, in case the user
// is currently dragging the canvas.
e.mouse_cursor(|new_pos| {
if canvas_follows_mouse {
let move_by = math::sub(new_pos, mouse_pos_px);
transform.move_by_px(move_by);
}
mouse_pos_px = new_pos;
mouse_pos_m = transform.point_px_to_m(new_pos);
});
// The zoom factor is changed with the mouse wheel.
e.mouse_scroll(|[_, y]| {
let scale_changed = if y < 0. && transform.try_zoom_in() {
true
} else if y > 0. && transform.try_zoom_out() {
true
} else {
false
};
// Notify the user of the change if there was any
if scale_changed {
grid.on_scale_change(&transform, window.draw_size());
println!(
"Changed scale to {} pixels per m.",
transform.pixels_per_m()
);
}
});
// Handle the movement of the canvas when pressing the middle mouse button.
if let Some(Button::Mouse(MouseButton::Middle)) = e.press_args() {
canvas_follows_mouse = true;
println!("Canvas now follows the mouse");
}
if let Some(Button::Mouse(MouseButton::Middle)) = e.release_args() {
canvas_follows_mouse = false;
println!("Canvas no longer follows the mouse");
}
// Handle drawing a rectangle or finishing the rectangle when clicking with the mouse.
if let Some(Button::Mouse(MouseButton::Left)) = e.press_args() {
if let Some(first_point) = starting_rect_point {
rectangles.push(bounding_box(first_point, mouse_pos_m));
starting_rect_point = None;
} else {
starting_rect_point = Some(mouse_pos_m);
}
}
// Abort drawing a rectangle when clicking with the right mouse button
if let Some(Button::Mouse(MouseButton::Right)) = e.press_args() {
starting_rect_point = None;
}
// Close the window when the user presses escape
if let Some(Button::Keyboard(Key::Escape)) = e.press_args() {
window.set_should_close(true);
}
window.draw_2d(&e, |c, g, _device| {
clear([0.4, 0.2, 0., 1.], g);
grid.draw(&transform, &c, g);
// Draw all rectangles that are part of the map
for &rect in &rectangles {
render_rect.draw(transform.rect_m_to_px(rect), &c.draw_state, c.transform, g);
}
// Draw the current rectangle that is being drawn, but not part of the map
if let Some(starting_rect_point) = starting_rect_point {
render_rect.draw(
transform.rect_m_to_px(bounding_box(starting_rect_point, mouse_pos_m)),
&c.draw_state,
c.transform,
g,
);
}
});
}
}
|