Skip to main content

plutonium_engine/
camera.rs

1use crate::{Position, Rectangle, Size};
2use uuid::Uuid;
3
4#[derive(Debug)]
5pub struct Camera {
6    position: Position,
7    boundary: Option<Rectangle>,
8    activated: bool,
9    pub tether_target: Option<Uuid>,
10    tether_size: Option<Size>,
11}
12
13impl Camera {
14    pub fn set_boundary(&mut self, boundary: Rectangle) {
15        self.boundary = Some(boundary);
16    }
17
18    pub fn clear_boundary(&mut self) {
19        self.boundary = None;
20    }
21
22    pub fn activate(&mut self) {
23        self.activated = true;
24    }
25
26    pub fn deactivate(&mut self) {
27        self.activated = false;
28    }
29
30    pub fn get_pos(&self, scale_factor: f32) -> Position {
31        if self.activated {
32            Position {
33                x: self.position.x * scale_factor,
34                y: self.position.y * scale_factor,
35            }
36        } else {
37            Position { x: 0.0, y: 0.0 }
38        }
39    }
40    pub fn set_pos(&mut self, new_pos: Position) {
41        if let Some(boundary) = &self.boundary {
42            // Calculate the logical boundary taking into account both camera position and tether size
43            let logical_boundary = if let Some(tether_size) = self.tether_size {
44                Rectangle::new(
45                    boundary.x + self.position.x,
46                    boundary.y + self.position.y,
47                    boundary.width - tether_size.width,
48                    boundary.height - tether_size.height,
49                )
50            } else {
51                Rectangle::new(
52                    boundary.x + self.position.x,
53                    boundary.y + self.position.y,
54                    boundary.width,
55                    boundary.height,
56                )
57            };
58
59            // Handle the x-direction
60            let dx = {
61                let right_overflow = new_pos.x - (logical_boundary.x + logical_boundary.width);
62                let left_overflow = new_pos.x - logical_boundary.x;
63                if right_overflow > 0.0 {
64                    right_overflow
65                } else if left_overflow < 0.0 {
66                    left_overflow
67                } else {
68                    0.0
69                }
70            };
71            self.position.x += dx;
72
73            // Handle the y-direction
74            let dy = {
75                let bottom_overflow = new_pos.y - (logical_boundary.y + logical_boundary.height);
76                let top_overflow = new_pos.y - logical_boundary.y;
77                if bottom_overflow > 0.0 {
78                    bottom_overflow
79                } else if top_overflow < 0.0 {
80                    top_overflow
81                } else {
82                    0.0
83                }
84            };
85            self.position.y += dy;
86        } else {
87            // If no boundary is set, simply update the position
88            self.position = new_pos;
89        }
90    }
91
92    pub fn new(position: Position) -> Self {
93        Self {
94            position,
95            tether_target: None,
96            activated: false,
97            boundary: None,
98            tether_size: None,
99        }
100    }
101
102    pub fn set_tether_target(&mut self, target: Option<Uuid>) {
103        self.tether_target = target;
104    }
105
106    pub fn set_tether_size(&mut self, size: Option<Size>) {
107        self.tether_size = size;
108    }
109}