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
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use crate::prelude::*;

use crate::macroquad::prelude::draw_texture_ex;

pub struct PostProcessing {
    lighting_material: Option<Material>,
    effect_material: Option<Material>,
    current_effect_material_id: Option<String>,
}

impl PostProcessing {
    const LIGHTING_MATERIAL_ID: &'static str = "dynamic_lighting";

    pub fn new() -> Result<Self> {
        let mut res = PostProcessing {
            lighting_material: None,
            effect_material: None,
            current_effect_material_id: None,
        };

        res.apply_config()?;

        Ok(res)
    }

    pub fn add_node() -> Result<Handle<Self>> {
        let node = Self::new()?;
        let res = scene::add_node(node);

        Ok(res)
    }

    // Apply current configuration from Config in storage.
    // This is called on construction but should also be called if config changes.
    // It does its own cleanup with deletion of compiled materials, where necessary.
    pub fn apply_config(&mut self) -> Result<()> {
        let resources = storage::get::<Resources>();
        let config = storage::get::<Config>();

        if config.dynamic_lighting {
            if self.lighting_material.is_none() {
                let mut material = resources
                    .materials
                    .get(Self::LIGHTING_MATERIAL_ID)
                    .cloned()
                    .unwrap();
                material.compile()?;
                self.lighting_material = Some(material);
            }
        } else if let Some(lighting_material) = &mut self.lighting_material {
            lighting_material.delete_compiled()?;
            self.lighting_material = None;
        }

        let mut should_load_effect_material = false;
        if let Some(material_id) = &config.post_processing {
            if material_id != "none" {
                should_load_effect_material = true;
            }
        }

        if should_load_effect_material {
            let material_id = config.post_processing.clone().unwrap();
            if let Some(current_id) = self.current_effect_material_id.clone() {
                if current_id != material_id {
                    let material = self.effect_material.as_mut().unwrap();
                    material.delete_compiled()?;
                    self.effect_material = None;
                    self.current_effect_material_id = None;
                }
            }

            if self.effect_material.is_none() {
                let mut material = resources.materials.get(&material_id).cloned().unwrap();
                material.compile()?;
                self.effect_material = Some(material);
                self.current_effect_material_id = Some(material_id);
            }
        } else if let Some(material) = &mut self.effect_material {
            material.delete_compiled()?;
            self.effect_material = None;
            self.current_effect_material_id = None;
        }

        Ok(())
    }
}

impl Node for PostProcessing {
    fn draw(node: RefMut<Self>) {
        let camera = scene::find_node_by_type::<CameraController>().unwrap();

        if let Some(material) = &node.lighting_material {
            use_material(material).unwrap();

            for _light in scene::find_nodes_by_type::<LightSource>() {}
        }

        set_default_camera();

        if let Some(material) = &node.effect_material {
            use_material(material).unwrap();
        } else {
            use_default_material();
        }

        let render_target = camera.get_render_target().unwrap();
        draw_texture_ex(
            render_target.texture,
            0.0,
            0.0,
            color::WHITE,
            DrawTextureParams {
                dest_size: Some(vec2(get_screen_width(), get_screen_height())),
                ..Default::default()
            },
        );

        use_default_material();
    }
}