Skip to main content

bevy_feronia/wind/
plugin.rs

1use super::systems::*;
2use crate::prelude::*;
3
4use bevy_app::{App, Plugin, PreUpdate, Startup, Update};
5use bevy_asset::Assets;
6use bevy_ecs::prelude::*;
7use bevy_pbr::StandardMaterial;
8use bevy_shader::load_shader_library;
9use std::fmt::Debug;
10use std::marker::PhantomData;
11
12pub struct WindPlugin;
13
14#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
15pub struct WindTextureSetup;
16
17impl Plugin for WindPlugin {
18    fn build(&self, app: &mut App) {
19        load_shader_library!(app, "types.wgsl");
20        load_shader_library!(app, "wind.wgsl");
21        load_shader_library!(app, "bindings.wgsl");
22        load_shader_library!(app, "noise.wgsl");
23        load_shader_library!(app, "displace.wgsl");
24        load_shader_library!(app, "forward_sss_io.wgsl");
25
26        app.register_type::<GlobalWind>()
27            .register_type::<Wind>()
28            .init_resource::<GlobalWind>()
29            .configure_sets(Startup, WindTextureSetup)
30            .add_systems(Startup, setup_wind_texture.in_set(WindTextureSetup))
31            .add_systems(
32                PreUpdate,
33                (
34                    sync_wind_preset.run_if(resource_changed::<GlobalWind>),
35                    cycle_wind_history,
36                )
37                    .chain(),
38            );
39    }
40}
41
42pub struct ScatterMaterialPlugin<T = StandardMaterial>
43where
44    T: ScatterMaterial,
45{
46    pub _marker: PhantomData<T>,
47}
48
49impl<T> Default for ScatterMaterialPlugin<T>
50where
51    T: ScatterMaterial,
52{
53    fn default() -> Self {
54        Self {
55            _marker: PhantomData,
56        }
57    }
58}
59
60impl<T> ScatterMaterialPlugin<T>
61where
62    T: ScatterMaterial,
63{
64    pub fn new() -> Self {
65        Self::default()
66    }
67}
68
69impl<T> Plugin for ScatterMaterialPlugin<T>
70where
71    T: ScatterMaterial,
72{
73    fn build(&self, app: &mut App) {
74        app.add_systems(
75            Update,
76            (update_materials::<T>.run_if(
77                resource_changed::<GlobalWind>
78                    .or(material_options_changed)
79                    .and(resource_exists::<Assets<ScatterAsset<T>>>)
80                    .and(resource_exists::<ScatterAssetManager<T>>),
81            ),),
82        );
83    }
84}
85
86// TODO granular updates && updating base color / properties (unlit)
87fn material_options_changed(
88    q_layer_changed: Query<(), (Or<(MaterialChangedFilter, WindChangedFilter)>,)>,
89    q_root_changed: Query<
90        (),
91        (
92            With<ScatterRoot>,
93            Or<(MaterialChangedFilter, WindChangedFilter)>,
94        ),
95    >,
96) -> bool {
97    !q_layer_changed.is_empty() || !q_root_changed.is_empty()
98}