bevy_feronia/scatter/
plugin.rs1use 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}