1use nalgebra;
20use nalgebra::Matrix4;
21use rect::Rect;
22use {Point, Vector};
23
24#[derive(Debug, Clone, PartialEq)]
29pub struct View {
30 projection: Matrix4<f32>,
31 sizes: Vector<f32>,
32 pos: Vector<f32>,
33 screen: Rect<f32>,
34 angle: f32,
35 zoom: f32,
36 need_update: bool,
37}
38
39impl View {
40 pub fn new(pos: Point<f32>, rect: Rect<f32>) -> View {
42 View {
43 projection: Matrix4::new_ortho(
44 rect.left as f32,
45 rect.width as f32,
46 rect.top as f32,
47 rect.height as f32,
48 -1.0,
49 1.0,
50 ),
51 zoom: 1.0,
52 angle: 0.0,
53 sizes: Vector::new(rect.width, rect.height),
54 pos,
55 screen: Rect::new(1.0, 1.0, 1.0, 1.0),
56 need_update: false,
57 }
58 }
59
60 pub fn reset(&mut self, rect: Rect<f32>) {
62 self.projection = Matrix4::new_orthographic(
63 rect.left as f32,
64 rect.width as f32,
65 rect.top as f32,
66 rect.height as f32,
67 -1.0,
68 1.0,
69 );
70 self.sizes = Vector::new(rect.width, rect.height);
71 self.need_update = true;
72 }
73
74 pub fn set_center(&mut self, pos: Point<f32>) {
76 self.pos.x = pos.x - self.sizes.x / 2.0;
77 self.pos.y = pos.y - self.sizes.y / 2.0;
78 self.need_update = true;
79 }
80
81 pub fn set_viewport(&mut self, viewport: Rect<f32>) {
84 self.screen = viewport;
85 }
86
87 pub fn set_sizes(&mut self, sizes: Vector<f32>) {
89 self.sizes.x = sizes.x;
90 self.sizes.y = sizes.y;
91 }
92
93 pub fn translate<T: nalgebra::Scalar + Into<f32>>(&mut self, offset: Vector<T>) {
95 self.pos.x += offset.x.into();
96 self.pos.y += offset.y.into();
97 self.need_update = true;
98 }
99
100 pub fn update(&mut self) {
102 if self.need_update {
103 let width = self.sizes.x * self.zoom;
104 let height = self.sizes.y * self.zoom;
105
106 self.projection = Matrix4::new_ortho(
107 self.pos.x,
108 width + self.pos.x,
109 height + self.pos.y,
110 self.pos.y,
111 -1.0,
112 1.0,
113 );
114 self.need_update = false;
115 }
116 }
117
118 pub fn set_zoom(&mut self, zoom: f32) {
120 self.zoom = zoom;
121 self.need_update = true;
122 }
123
124 pub fn zoom(&mut self, zoom: f32) {
126 self.zoom *= 1.0 / zoom;
127 self.need_update = true;
128 }
129
130 pub fn get_zoom(&self) -> f32 {
132 self.zoom
133 }
134
135 pub fn projection(&self) -> &Matrix4<f32> {
137 &self.projection
138 }
139
140 pub fn sizes(&self) -> Vector<f32> {
142 self.sizes
143 }
144
145 pub fn postition(&self) -> Vector<f32> {
147 self.pos
148 }
149}
150
151impl From<Rect<f32>> for View {
152 fn from(rect: Rect<f32>) -> View {
153 let proj = Matrix4::new_ortho(
154 rect.left,
155 rect.width + rect.left,
156 rect.height + rect.top,
157 rect.top,
158 -1.0,
159 1.0,
160 );
161 View {
162 pos: Vector::new(rect.left, rect.top),
163 projection: proj,
164 sizes: Vector::new(rect.width, rect.height),
165 need_update: false,
166 zoom: 1.0,
167 angle: 0.0,
168 screen: Rect::new(0.0, 0.0, 1.0, 1.0),
169 }
170 }
171}
172
173impl Ortho for Matrix4<f32> {}
175
176trait Ortho {
178 fn new_ortho(
179 left: f32,
180 right: f32,
181 bottom: f32,
182 top: f32,
183 near: f32,
184 far: f32,
185 ) -> Matrix4<f32> {
186 let width = right - left;
187 let height = top - bottom;
188 let a = 2.0 / width;
189 let b = 2.0 / height;
190 let c = -2.0 / (far - near);
191 let tx = -(right + left) / width;
192 let ty = -(top + bottom) / height;
193 let tz = -(far + near) / far - near;
194
195 Matrix4::new(
196 a, 0.0, 0.0, tx, 0.0, b, 0.0, ty, 0.0, 0.0, c, tz, 0.0, 0.0, 0.0, 1.0,
197 )
198 }
199}