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
use crate::drawable::*;
use crate::mouse::*;
use crate::system::*;

pub trait Widget {
    fn draw(&self, target: &mut glium::Frame, system: &System) {
        if let Some(mut drawable) = self.drawable() {
            let matrix = self.matrix();
            system.draw::<glium::Frame, [[f32; 4]; 4]>(&mut drawable, target, matrix);
        }
    }
    fn position(&self) -> (f32, f32);
    fn size(&self) -> (f32, f32);
    fn size_adjusted(&self) -> (f32, f32) {
        let (w, h) = self.size();
        (w * 2.0, h * 2.0)
    }
    fn position_adjusted(&self) -> (f32, f32) {
        let (x, y) = self.position();
        let (x, y) = (x * 2.0 - 1.0, y * 2.0 - 1.0);
        let (w, h) = self.size_adjusted();
        let (x, y) = (x + w / 2.0, y + h / 2.0);
        (x, y)
    }
    fn translate(&self, mat: [[f32; 4]; 4]) -> [[f32; 4]; 4] {
        let (x, y) = self.position_adjusted();

        let translation = nalgebra::Vector3::new(x, -y, 0.0);

        let mat = nalgebra::Matrix4::from(mat);
        let mat = mat.append_translation(&translation);
        mat.into()
    }
    fn scale(&self, mat: [[f32; 4]; 4]) -> [[f32; 4]; 4] {
        let mut mat = mat;
        let (w, h) = self.size_adjusted();

        mat[0][0] *= w;
        mat[1][1] *= h;

        mat
    }
    fn drawable(&self) -> Option<Drawable>;
    fn matrix(&self) -> [[f32; 4]; 4] {
        let mat = [
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [0.0, 0.0, 0.0, 1.0],
        ];
        let mat = self.translate(mat);
        let mat = self.scale(mat);
        mat
    }
}

pub trait Pressable: Widget {
    fn left(&self) -> &ButtonState;
    fn middle(&self) -> &ButtonState;
    fn right(&self) -> &ButtonState;
    fn update(&mut self, mouse: &MouseStatus);
}

pub trait Rotatable: Widget {
    fn rotation(&self) -> f32;
    fn rotate(&self, mat: [[f32; 4]; 4]) -> [[f32; 4]; 4] {
        let rotation = self.rotation() / 360.0 * 2.0 * std::f32::consts::PI;
        let rotation = nalgebra::Matrix4::from_euler_angles(0.0, 0.0, rotation);

        let mat = nalgebra::Matrix4::from(mat);
        let mat = mat * rotation;
        mat.into()
    }
}