blob: 34924c33ec9a4b0cb78ea94780d94472d5b19265 [file] [log] [blame]
use egui::{pos2, Pos2, Rect, Vec2};
pub trait ScreenBounds {
fn zoom_point(&mut self, center: Pos2, zoom_factor: f32);
fn calc_scale(&self, screen_bounds: Rect) -> f32;
fn translate(&mut self, delta: Vec2);
fn screen_pos_to_world(&self, screen_point: Pos2, screen_bounds: Rect) -> Pos2;
fn world_pos_to_screen(&self, world_point: Pos2, screen_bounds: Rect) -> Pos2;
fn screen_rect_to_world(&self, screen_rect: Rect, screen_bounds: Rect) -> Rect;
fn world_rect_to_screen(&self, world_rect: Rect, screen_bounds: Rect) -> Rect;
}
impl ScreenBounds for Rect {
fn zoom_point(&mut self, center: Pos2, zoom_factor: f32) {
let mut left = center.x - self.left();
let mut right = self.right() - center.x;
left *= zoom_factor;
right *= zoom_factor;
let mut top = center.y - self.top();
let mut bottom = self.bottom() - center.y;
top *= zoom_factor;
bottom *= zoom_factor;
self.set_left(center.x - left);
self.set_right(center.x + right);
self.set_top(center.y - top);
self.set_bottom(center.y + bottom);
}
fn calc_scale(&self, screen_bounds: Rect) -> f32 {
let x_scale = screen_bounds.width() / (self.right() - self.left());
let y_scale = screen_bounds.height() / (self.bottom() - self.top());
x_scale.min(y_scale)
}
fn translate(&mut self, delta: Vec2) {
self.set_left(self.left() - delta.x);
self.set_right(self.right() - delta.x);
self.set_top(self.top() - delta.y);
self.set_bottom(self.bottom() - delta.y);
}
fn screen_pos_to_world(&self, screen_point: Pos2, screen_bounds: Rect) -> Pos2 {
let scale = self.calc_scale(screen_bounds);
let world_x = (screen_point.x - screen_bounds.left()) / scale + self.left();
let world_y = (screen_point.y - screen_bounds.top()) / scale + self.top();
pos2(world_x, world_y)
}
fn world_pos_to_screen(&self, world_point: Pos2, screen_bounds: Rect) -> Pos2 {
let scale = self.calc_scale(screen_bounds);
let screen_x = (world_point.x - self.left()) * scale + screen_bounds.left();
let screen_y = (world_point.y - self.top()) * scale + screen_bounds.top();
pos2(screen_x, screen_y)
}
fn screen_rect_to_world(&self, screen_rect: Rect, screen_bounds: Rect) -> Rect {
let left_top = self.screen_pos_to_world(screen_rect.left_top(), screen_bounds);
let right_bottom = self.screen_pos_to_world(screen_rect.right_bottom(), screen_bounds);
Rect::from_min_max(left_top, right_bottom)
}
fn world_rect_to_screen(&self, world_rect: Rect, screen_bounds: Rect) -> Rect {
let left_top = self.world_pos_to_screen(world_rect.left_top(), screen_bounds);
let right_bottom = self.world_pos_to_screen(world_rect.right_bottom(), screen_bounds);
Rect::from_min_max(left_top, right_bottom)
}
}