mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
add scene instance entity iteration (#1058)
add scene instance entity iteration
This commit is contained in:
parent
030ccf1984
commit
c25b41a038
4 changed files with 126 additions and 11 deletions
12
Cargo.toml
12
Cargo.toml
|
@ -106,6 +106,10 @@ path = "examples/2d/contributors.rs"
|
|||
name = "text2d"
|
||||
path = "examples/2d/text2d.rs"
|
||||
|
||||
[[example]]
|
||||
name = "3d_scene"
|
||||
path = "examples/3d/3d_scene.rs"
|
||||
|
||||
[[example]]
|
||||
name = "load_gltf"
|
||||
path = "examples/3d/load_gltf.rs"
|
||||
|
@ -118,10 +122,6 @@ path = "examples/3d/msaa.rs"
|
|||
name = "parenting"
|
||||
path = "examples/3d/parenting.rs"
|
||||
|
||||
[[example]]
|
||||
name = "3d_scene"
|
||||
path = "examples/3d/3d_scene.rs"
|
||||
|
||||
[[example]]
|
||||
name = "spawner"
|
||||
path = "examples/3d/spawner.rs"
|
||||
|
@ -130,6 +130,10 @@ path = "examples/3d/spawner.rs"
|
|||
name = "texture"
|
||||
path = "examples/3d/texture.rs"
|
||||
|
||||
[[example]]
|
||||
name = "update_gltf_scene"
|
||||
path = "examples/3d/update_gltf_scene.rs"
|
||||
|
||||
[[example]]
|
||||
name = "z_sort_debug"
|
||||
path = "examples/3d/z_sort_debug.rs"
|
||||
|
|
|
@ -14,10 +14,10 @@ struct InstanceInfo {
|
|||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
struct InstanceId(Uuid);
|
||||
pub struct InstanceId(Uuid);
|
||||
|
||||
impl InstanceId {
|
||||
pub fn new() -> Self {
|
||||
fn new() -> Self {
|
||||
InstanceId(Uuid::new_v4())
|
||||
}
|
||||
}
|
||||
|
@ -51,15 +51,17 @@ impl SceneSpawner {
|
|||
self.dynamic_scenes_to_spawn.push(scene_handle);
|
||||
}
|
||||
|
||||
pub fn spawn(&mut self, scene_handle: Handle<Scene>) {
|
||||
pub fn spawn(&mut self, scene_handle: Handle<Scene>) -> InstanceId {
|
||||
let instance_id = InstanceId::new();
|
||||
self.scenes_to_spawn.push((scene_handle, instance_id));
|
||||
instance_id
|
||||
}
|
||||
|
||||
pub fn spawn_as_child(&mut self, scene_handle: Handle<Scene>, parent: Entity) {
|
||||
pub fn spawn_as_child(&mut self, scene_handle: Handle<Scene>, parent: Entity) -> InstanceId {
|
||||
let instance_id = InstanceId::new();
|
||||
self.scenes_to_spawn.push((scene_handle, instance_id));
|
||||
self.scenes_with_parent.push((instance_id, parent));
|
||||
instance_id
|
||||
}
|
||||
|
||||
pub fn despawn(&mut self, scene_handle: Handle<DynamicScene>) {
|
||||
|
@ -155,7 +157,7 @@ impl SceneSpawner {
|
|||
world: &mut World,
|
||||
resources: &Resources,
|
||||
scene_handle: Handle<Scene>,
|
||||
) -> Result<(), SceneSpawnError> {
|
||||
) -> Result<InstanceId, SceneSpawnError> {
|
||||
self.spawn_sync_internal(world, resources, scene_handle, InstanceId::new())
|
||||
}
|
||||
|
||||
|
@ -165,7 +167,7 @@ impl SceneSpawner {
|
|||
resources: &Resources,
|
||||
scene_handle: Handle<Scene>,
|
||||
instance_id: InstanceId,
|
||||
) -> Result<(), SceneSpawnError> {
|
||||
) -> Result<InstanceId, SceneSpawnError> {
|
||||
let mut instance_info = InstanceInfo {
|
||||
entity_map: EntityMap::default(),
|
||||
};
|
||||
|
@ -220,7 +222,7 @@ impl SceneSpawner {
|
|||
.entry(scene_handle)
|
||||
.or_insert_with(Vec::new);
|
||||
spawned.push(instance_id);
|
||||
Ok(())
|
||||
Ok(instance_id)
|
||||
}
|
||||
|
||||
pub fn update_spawned_scenes(
|
||||
|
@ -304,6 +306,21 @@ impl SceneSpawner {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that an scene instance spawned previously is ready to use
|
||||
pub fn instance_is_ready(&self, instance_id: InstanceId) -> bool {
|
||||
self.spawned_instances.contains_key(&instance_id)
|
||||
}
|
||||
|
||||
/// Get an iterator over the entities in an instance, once it's spawned
|
||||
pub fn iter_instance_entities(
|
||||
&'_ self,
|
||||
instance_id: InstanceId,
|
||||
) -> Option<impl Iterator<Item = Entity> + '_> {
|
||||
self.spawned_instances
|
||||
.get(&instance_id)
|
||||
.map(|instance| instance.entity_map.values())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scene_spawner_system(world: &mut World, resources: &mut Resources) {
|
||||
|
|
93
examples/3d/update_gltf_scene.rs
Normal file
93
examples/3d/update_gltf_scene.rs
Normal file
|
@ -0,0 +1,93 @@
|
|||
use bevy::{prelude::*, scene::InstanceId};
|
||||
|
||||
fn main() {
|
||||
App::build()
|
||||
.add_resource(Msaa { samples: 4 })
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_resource(SceneInstance::default())
|
||||
.add_startup_system(setup.system())
|
||||
.add_system(scene_update.system())
|
||||
.add_system(move_scene_entities.system())
|
||||
.run();
|
||||
}
|
||||
|
||||
// Resource to hold the scene `instance_id` until it is loaded
|
||||
#[derive(Default)]
|
||||
struct SceneInstance(Option<InstanceId>);
|
||||
|
||||
// Component that will be used to tag entities in the scene
|
||||
struct EntityInMyScene;
|
||||
|
||||
fn setup(
|
||||
commands: &mut Commands,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut scene_spawner: ResMut<SceneSpawner>,
|
||||
mut scene_instance: ResMut<SceneInstance>,
|
||||
) {
|
||||
commands
|
||||
.spawn(LightBundle {
|
||||
transform: Transform::from_translation(Vec3::new(4.0, 5.0, 4.0)),
|
||||
..Default::default()
|
||||
})
|
||||
.spawn(Camera3dBundle {
|
||||
transform: Transform::from_translation(Vec3::new(1.05, 0.9, 1.5))
|
||||
.looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::unit_y()),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
// Spawn the scene as a child of another entity. This first scene will be translated backward
|
||||
// with its parent
|
||||
commands
|
||||
.spawn((
|
||||
Transform::from_translation(Vec3::new(0.0, 0.0, -1.0)),
|
||||
GlobalTransform::default(),
|
||||
))
|
||||
.with_children(|parent| {
|
||||
parent.spawn_scene(asset_server.load("models/FlightHelmet/FlightHelmet.gltf"));
|
||||
});
|
||||
|
||||
// Spawn a second scene, and keep its `instance_id`
|
||||
let instance_id =
|
||||
scene_spawner.spawn(asset_server.load("models/FlightHelmet/FlightHelmet.gltf"));
|
||||
scene_instance.0 = Some(instance_id);
|
||||
}
|
||||
|
||||
// This system will wait for the scene to be ready, and then tag entities from
|
||||
// the scene with `EntityInMyScene`. All entities from the second scene will be
|
||||
// tagged
|
||||
fn scene_update(
|
||||
commands: &mut Commands,
|
||||
scene_spawner: Res<SceneSpawner>,
|
||||
scene_instance: Res<SceneInstance>,
|
||||
mut done: Local<bool>,
|
||||
) {
|
||||
if !*done {
|
||||
if let Some(instance_id) = scene_instance.0 {
|
||||
if let Some(entity_iter) = scene_spawner.iter_instance_entities(instance_id) {
|
||||
entity_iter.for_each(|entity| {
|
||||
commands.insert_one(entity, EntityInMyScene);
|
||||
});
|
||||
*done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This system will move all entities with component `EntityInMyScene`, so all
|
||||
// entities from the second scene
|
||||
fn move_scene_entities(
|
||||
time: Res<Time>,
|
||||
mut scene_entities: Query<&mut Transform, With<EntityInMyScene>>,
|
||||
) {
|
||||
let mut direction = 1.;
|
||||
let mut scale = 1.;
|
||||
for mut transform in scene_entities.iter_mut() {
|
||||
transform.translation = Vec3::new(
|
||||
scale * direction * time.seconds_since_startup().sin() as f32 / 20.,
|
||||
0.,
|
||||
time.seconds_since_startup().cos() as f32 / 20.,
|
||||
);
|
||||
direction *= -1.;
|
||||
scale += 0.5;
|
||||
}
|
||||
}
|
|
@ -73,6 +73,7 @@ Example | File | Description
|
|||
`parenting` | [`3d/parenting.rs`](./3d/parenting.rs) | Demonstrates parent->child relationships and relative transformations
|
||||
`spawner` | [`3d/spawner.rs`](./3d/spawner.rs) | Renders a large number of cubes with changing position and material
|
||||
`texture` | [`3d/texture.rs`](./3d/texture.rs) | Shows configuration of texture materials
|
||||
`update_gltf_scene` | [`3d/update_gltf_scene.rs`](./3d/update_gltf_scene.rs) | Update a scene from a gltf file, either by spawning the scene as a child of another entity, or by accessing the entities of the scene
|
||||
`z_sort_debug` | [`3d/z_sort_debug.rs`](./3d/z_sort_debug.rs) | Visualizes camera Z-ordering
|
||||
|
||||
## Application
|
||||
|
|
Loading…
Reference in a new issue