space_prefab/
spawn_system.rs

1use bevy::prelude::*;
2use bevy_scene_hook::{HookedSceneBundle, SceneHook};
3
4use super::component::*;
5
6/// System responsible for spawning GLTF objects in the scene
7pub fn spawn_scene(
8    mut commands: Commands,
9    prefabs: Query<
10        (
11            Entity,
12            &GltfPrefab,
13            Option<&Children>,
14            Option<&Visibility>,
15            Option<&Transform>,
16        ),
17        Changed<GltfPrefab>,
18    >,
19    auto_childs: Query<&SceneAutoChild>,
20    asset_server: Res<AssetServer>,
21) {
22    for (e, prefab, children, vis, tr) in prefabs.iter() {
23        if let Some(children) = children {
24            for e in children {
25                if auto_childs.contains(*e) {
26                    commands.entity(*e).despawn_recursive();
27                }
28            }
29        }
30
31        let id = commands
32            .spawn(HookedSceneBundle {
33                scene: SceneBundle {
34                    scene: asset_server.load(format!("{}#{}", &prefab.path, &prefab.scene)),
35                    ..default()
36                },
37                hook: SceneHook::new(|_e, cmd| {
38                    cmd.insert(SceneAutoChild);
39                }),
40            })
41            .insert(SceneAutoChild)
42            .id();
43        commands.entity(e).add_child(id);
44
45        if vis.is_none() {
46            commands.entity(e).insert(VisibilityBundle::default());
47        }
48        if tr.is_none() {
49            #[cfg(feature = "f32")]
50            commands.entity(e).insert(TransformBundle::default());
51            #[cfg(feature = "f64")]
52            {
53                commands
54                    .entity(e)
55                    .insert(bevy_transform64::DTransformBundle::default());
56            }
57        }
58    }
59}
60
61/// System to sync [`Mesh`] and [`MeshPrimitivePrefab`]
62pub fn sync_mesh(
63    mut commands: Commands,
64    query: Query<(Entity, &MeshPrimitivePrefab), Changed<MeshPrimitivePrefab>>,
65    mut meshs: ResMut<Assets<Mesh>>,
66) {
67    for (e, pref) in query.iter() {
68        let mesh = meshs.add(pref.to_mesh());
69        commands.entity(e).insert(mesh);
70    }
71}
72
73/// System to sync [`StandardMaterial`] and [`MaterialPrefab`]
74pub fn sync_material(
75    mut commands: Commands,
76    query: Query<(Entity, &MaterialPrefab), Changed<MaterialPrefab>>,
77    mut materials: ResMut<Assets<StandardMaterial>>,
78    asset_server: Res<AssetServer>,
79) {
80    for (e, pref) in query.iter() {
81        let mat = materials.add(pref.to_material(&asset_server));
82        commands.entity(e).insert(mat);
83    }
84}
85
86/// remove mesh handle if prefab struct was removed in editor states
87pub fn editor_remove_mesh(
88    mut commands: Commands,
89    mut query: RemovedComponents<MeshPrimitivePrefab>,
90) {
91    for e in query.read() {
92        if let Some(mut cmd) = commands.get_entity(e) {
93            cmd.remove::<Handle<Mesh>>();
94            info!("Removed mesh handle for {:?}", e);
95        }
96    }
97}
98
99/// Spawn system on enter to [`EditorState::Game`] state
100///
101/// [`EditorState::Game`]: crate::EditorState::Game
102pub fn spawn_player_start(
103    mut commands: Commands,
104    query: Query<(Entity, &PlayerStart)>,
105    asset_server: Res<AssetServer>,
106) {
107    for (e, prefab) in query.iter() {
108        info!("Spawning player start {:?} {}", e, &prefab.prefab);
109        let child = commands
110            .spawn(DynamicSceneBundle {
111                scene: asset_server.load(prefab.prefab.to_string()),
112                ..default()
113            })
114            .id();
115        commands.entity(e).add_child(child);
116    }
117}
118
119// pub fn despawn_player_start(
120//     mut commands : Commands,
121//     query : Query<Entity, (With<PlayerStart>, With<Handle<Scene>>)>
122// ) {
123//     for e in query.iter() {
124
125//     }
126// }