Newer
Older
use bevy::ecs::query::ReadOnlyWorldQuery;
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;
use crate::MapQuery;
pub fn lock_camera_to_level<CameraSelector: ReadOnlyWorldQuery>(
map_query: MapQuery,
mut camera_query: Query<(&mut Transform, &OrthographicProjection), CameraSelector>,
) {
let bounds = match map_query.get_camera_bounds() {
Some(bounds) => bounds,
None => return,
};
for (mut transform, proj) in &mut camera_query {
let rect = proj.area;
let width = rect.width();
let height = rect.height();
let val_x = bounds
.get_min_x(width)
.max(bounds.get_max_x(width).min(transform.translation.x));
let val_y = bounds
.get_min_y(height)
.max(bounds.get_max_y(height).min(transform.translation.y));
transform.translation = Vec3::new(val_x, val_y, transform.translation.z);
}
}
#[derive(SystemParam)]
pub struct CameraBounder<'w, 's, Filter: ReadOnlyWorldQuery + 'static> {
map_query: MapQuery<'w, 's>,
query: Query<'w, 's, &'static OrthographicProjection, Filter>,
}
impl<'w, 's, Filter: ReadOnlyWorldQuery + 'static> CameraBounder<'w, 's, Filter> {
pub fn get_extremeties(&self) -> Option<Rect> {
if let Some(bounds) = self.map_query.get_camera_bounds() {
if let Ok(proj) = self.query.get_single() {
let rect = proj.area;
let width = rect.width();
let height = rect.height();
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
Some(Rect::new(
bounds.get_min_x(width),
bounds.get_min_y(height),
bounds.get_max_x(width),
bounds.get_max_y(height),
))
} else {
None
}
} else {
None
}
}
pub fn bind(&self, point: Vec2) -> Vec2 {
if let Some(bounds) = self.get_extremeties() {
bounds.min.max(point).min(bounds.max)
} else {
point
}
}
}
#[cfg(test)]
mod test {
use bevy::math::{Rect, Vec2};
#[test]
fn min_max_vec() {
let initial_point = Vec2::new(3.0, 5.0);
let expected_point = Vec2::new(3.0, 3.0);
let bounds = Rect::new(1.0, 1.0, 3.0, 3.0);
assert_eq!(
expected_point,
bounds.min.max(initial_point).min(bounds.max)
);
}
}