tuigui/widgets/
shader_container.rs

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use crate::preludes::widget_creation::*;
use crate::Shader;

#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Shaders<S: Shader> {
    Single(S),
    Many(Vec<S>),
}

impl<S: Shader> Shaders<S> {
    fn apply(&mut self, canvas: &mut Canvas) {
        for col in 0..canvas.transform.size.cols {
            for row in 0..canvas.transform.size.rows {
                let position = Position::new(col as i16, row as i16);

                match self {
                    Self::Single(ref mut single) => {
                        apply(
                            single,
                            canvas,
                            position,
                        );
                    },
                    Self::Many(many) => {
                        for shader in many {
                            apply(
                                shader,
                                canvas,
                                position,
                            );
                        }
                    },
                };
            }
        }
    }
}

fn apply<S: Shader>(
    shader: &mut S,
    canvas: &mut Canvas,
    local_position: Position,
) {
    let shader_config = shader.config();

    let real_position = canvas.transform.position + local_position;

    let shader_position = match shader_config.real_position {
        true => real_position,
        false => local_position,
    };

    if shader_config.whole_area == false {
        if canvas.changed_at(local_position) == false {
            return;
        }
    }

    let content = canvas.get(local_position);

    let result = shader.apply(canvas, shader_position, content);

    canvas.set(local_position, result);
}

#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
/// Apply shaders to a widget
pub struct ShaderContainer<W: Widget, S: Shader> {
    pub widget: W,
    pub shaders: Shaders<S>,
    widget_data: WidgetData,
}

impl<W: Widget, S: Shader> ShaderContainer<W, S> {
    pub fn new(shaders: Shaders<S>, widget: W) -> Self {
        Self {
            widget,
            shaders,
            widget_data: WidgetData::new(),
        }
    }
}

impl<W: Widget, S: Shader> Widget for ShaderContainer<W, S> {
    fn draw(&mut self, canvas: &mut Canvas, state_frame: &EventStateFrame) {
        self.widget.draw(canvas, state_frame);
        self.shaders.apply(canvas);
    }

    fn widget_info(&self) -> WidgetInfo {
        return self.widget.widget_info();
    }

    fn widget_data(&mut self) -> &mut WidgetData {
        return &mut self.widget_data;
    }
}