Skip to main content

bevy_feronia/scatter/
plugin.rs

1use crate::backend::ScatterApp;
2use crate::core::events::SpawnScatterAssets;
3use crate::prelude::*;
4use crate::scatter::{observers::*, systems::prelude::*};
5use crate::{
6    asset::backend::systems::{insert_parts, insert_requests},
7    asset::systems::*,
8};
9
10use bevy_app::prelude::*;
11use bevy_asset::prelude::{AssetApp, Assets};
12use bevy_ecs::{prelude::resource_exists, schedule::IntoScheduleConfigs};
13use bevy_pbr::prelude::StandardMaterial;
14use bevy_state::prelude::*;
15
16use bevy_transform::TransformSystems;
17use std::marker::PhantomData;
18
19pub struct ScatterAssetPlugin<T = StandardMaterial>
20where
21    T: ScatterMaterial,
22{
23    _marker: PhantomData<T>,
24}
25
26impl<T> ScatterAssetPlugin<T>
27where
28    T: ScatterMaterial,
29{
30    pub fn new() -> Self {
31        Self {
32            _marker: PhantomData,
33        }
34    }
35}
36
37impl<T> Default for ScatterAssetPlugin<T>
38where
39    T: ScatterMaterial,
40{
41    fn default() -> Self {
42        Self::new()
43    }
44}
45
46impl<T> Plugin for ScatterAssetPlugin<T>
47where
48    T: ScatterMaterial,
49{
50    fn build(&self, app: &mut App) {
51        if !app.is_plugin_added::<ScatterPlugin>() {
52            app.add_plugins(ScatterPlugin);
53        }
54
55        app.init_resource::<SpawnScatterAssetsEventQueue<T>>()
56            .init_resource::<ScatterAssetManager<T>>()
57            .init_asset::<ScatterAsset<T>>()
58            .add_observer(on_add_scatter_root::<T>)
59            .add_observer(on_add_scatter_layer::<T>)
60            .add_observer(on_chunk_add::<T>)
61            .add_systems(
62                PreUpdate,
63                process_scatter_queue::<T>.in_set(ScatterSet::Ready),
64            )
65            .add_systems(
66                Update,
67                (
68                    manage_asset_lifecycle::<T>,
69                    chunk_init_scatter::<T>.in_set(ChunkSet::Ready),
70                    (
71                        handle_finished_scatter_tasks::<T>,
72                        spawn::<T>.run_if(resource_exists::<Assets<ScatterAsset<T>>>),
73                    )
74                        .in_set(ScatterSet::Ready),
75                ),
76            )
77            .add_systems(
78                PostUpdate,
79                handle_scatter_requests::<T>
80                    .after(TransformSystems::Propagate)
81                    .in_set(ScatterSet::Ready),
82            );
83    }
84}
85
86pub struct ScatterPlugin;
87
88impl Plugin for ScatterPlugin {
89    fn build(&self, app: &mut App) {
90        app.configure_scatter_sets()
91            .add_plugins((
92                ChunkPlugin,
93                HeightMapPlugin,
94                WindPlugin,
95                ScatterOccupancyMapPlugin,
96            ))
97            .init_state::<ScatterState>()
98            .init_resource::<WorldSeed>()
99            .add_message::<ClearScatterLayer>()
100            .add_message::<ClearScatterRoot>()
101            .add_observer(on_add_scatter_item)
102            .add_systems(
103                Update,
104                (
105                    transition_to_collecting.in_set(ScatterSet::Setup),
106                    (
107                        check_unprocessed_layers,
108                        check_unprocessed_items,
109                        check_unprocessed_root,
110                    )
111                        .in_set(ScatterSet::Collecting),
112                    clear_scatter_roots.in_set(ScatterSet::Ready),
113                    (clear_chunks, clear_scatter_layers).in_set(ScatterSet::Clean),
114                ),
115            )
116            .add_systems(
117                PostUpdate,
118                setup_root_aabb
119                    .in_set(ScatterSet::Setup)
120                    .after(TransformSystems::Propagate),
121            );
122    }
123}
124
125pub struct StandardScatterPlugin;
126
127impl Plugin for StandardScatterPlugin {
128    fn build(&self, app: &mut App) {
129        app.add_message::<SpawnScatterAssets>()
130            .add_message::<SpawnScatterAssets>()
131            .add_plugins((
132                ScatterMaterialPlugin::<StandardMaterial>::new(),
133                StandardScatterAssetRequestPlugin,
134                ScatterAssetPlugin::<StandardMaterial>::new(),
135            ));
136    }
137}
138
139pub struct StandardScatterAssetRequestPlugin;
140
141impl Plugin for StandardScatterAssetRequestPlugin {
142    fn build(&self, app: &mut App) {
143        app.add_systems(
144            PostUpdate,
145            (
146                insert_parts::<StandardMaterial>,
147                insert_requests::<StandardMaterial>,
148            )
149                .in_set(ScatterSet::Collecting),
150        )
151        .add_systems(
152            Update,
153            process_standard_requests.in_set(ScatterSet::Collecting),
154        );
155    }
156}