From eb51b4c28eac56492856ec263389bc56547f9133 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 1 Oct 2024 22:42:11 +0000 Subject: [PATCH] Migrate scenes to required components (#15579) # Objective A step in the migration to required components: scenes! ## Solution As per the [selected proposal](https://hackmd.io/@bevy/required_components/%2FPJtNGVMMQhyM0zIvCJSkbA): - Deprecate `SceneBundle` and `DynamicSceneBundle`. - Add `SceneRoot` and `DynamicSceneRoot` components, which wrap a `Handle` and `Handle` respectively. ## Migration Guide Asset handles for scenes and dynamic scenes must now be wrapped in the `SceneRoot` and `DynamicSceneRoot` components. Raw handles as components no longer spawn scenes. Additionally, `SceneBundle` and `DynamicSceneBundle` have been deprecated. Instead, use the scene components directly. Previously: ```rust let model_scene = asset_server.load(GltfAssetLabel::Scene(0).from_asset("model.gltf")); commands.spawn(SceneBundle { scene: model_scene, transform: Transform::from_xyz(-4.0, 0.0, -3.0), ..default() }); ``` Now: ```rust let model_scene = asset_server.load(GltfAssetLabel::Scene(0).from_asset("model.gltf")); commands.spawn(( SceneRoot(model_scene), Transform::from_xyz(-4.0, 0.0, -3.0), )); ``` --- crates/bevy_animation/src/lib.rs | 2 +- crates/bevy_gltf/src/lib.rs | 27 ++++++--------- crates/bevy_scene/src/bundle.rs | 45 ++++++++++++++----------- crates/bevy_scene/src/components.rs | 36 ++++++++++++++++++++ crates/bevy_scene/src/dynamic_scene.rs | 5 +-- crates/bevy_scene/src/lib.rs | 21 +++++++----- crates/bevy_scene/src/scene.rs | 5 +-- crates/bevy_scene/src/scene_spawner.rs | 5 +-- examples/3d/anisotropy.rs | 9 +++-- examples/3d/anti_aliasing.rs | 8 ++--- examples/3d/atmospheric_fog.rs | 8 ++--- examples/3d/clearcoat.rs | 15 ++++----- examples/3d/color_grading.rs | 23 ++++++------- examples/3d/deferred_rendering.rs | 14 +++----- examples/3d/depth_of_field.rs | 10 ++---- examples/3d/irradiance_volumes.rs | 26 +++++--------- examples/3d/lightmaps.rs | 8 ++--- examples/3d/load_gltf.rs | 8 ++--- examples/3d/load_gltf_extras.rs | 8 ++--- examples/3d/pcss.rs | 7 ++-- examples/3d/post_processing.rs | 23 ++++++------- examples/3d/query_gltf_primitives.rs | 12 +++---- examples/3d/reflection_probes.rs | 7 ++-- examples/3d/split_screen.rs | 7 ++-- examples/3d/ssr.rs | 16 ++++----- examples/3d/tonemapping.rs | 24 ++++++------- examples/3d/update_gltf_scene.rs | 20 +++++------ examples/3d/visibility_range.rs | 24 ++++++------- examples/3d/volumetric_fog.rs | 10 ++---- examples/animation/animated_fox.rs | 7 ++-- examples/animation/animation_graph.rs | 11 +++--- examples/animation/animation_masks.rs | 11 +++--- examples/animation/gltf_skinned_mesh.rs | 8 ++--- examples/animation/morph_targets.rs | 8 ++--- examples/asset/hot_asset_reloading.rs | 5 +-- examples/asset/multi_asset_sync.rs | 6 +--- examples/camera/projection_zoom.rs | 14 ++++---- examples/games/alien_cake_addict.rs | 31 +++++++++-------- examples/games/loading_screen.rs | 15 ++------- examples/scene/scene.rs | 9 ++--- examples/stress_tests/many_foxes.rs | 9 +++-- examples/transforms/align.rs | 7 ++-- examples/window/multiple_windows.rs | 7 ++-- 43 files changed, 272 insertions(+), 309 deletions(-) create mode 100644 crates/bevy_scene/src/components.rs diff --git a/crates/bevy_animation/src/lib.rs b/crates/bevy_animation/src/lib.rs index c9d821b3d57bb..39a8349d81212 100755 --- a/crates/bevy_animation/src/lib.rs +++ b/crates/bevy_animation/src/lib.rs @@ -653,7 +653,7 @@ impl ActiveAnimation { /// Animation controls. /// -/// Automatically added to any root animations of a `SceneBundle` when it is +/// Automatically added to any root animations of a scene when it is /// spawned. #[derive(Component, Default, Reflect)] #[reflect(Component, Default)] diff --git a/crates/bevy_gltf/src/lib.rs b/crates/bevy_gltf/src/lib.rs index df8ff45b72d5b..05d4c596f8469 100644 --- a/crates/bevy_gltf/src/lib.rs +++ b/crates/bevy_gltf/src/lib.rs @@ -22,15 +22,14 @@ //! # use bevy_gltf::prelude::*; //! //! fn spawn_gltf(mut commands: Commands, asset_server: Res) { -//! commands.spawn(SceneBundle { +//! commands.spawn(( //! // This is equivalent to "models/FlightHelmet/FlightHelmet.gltf#Scene0" //! // The `#Scene0` label here is very important because it tells bevy to load the first scene in the glTF file. //! // If this isn't specified bevy doesn't know which part of the glTF file to load. -//! scene: asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), +//! SceneRoot(asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf"))), //! // You can use the transform to give it a position -//! transform: Transform::from_xyz(2.0, 0.0, -5.0), -//! ..Default::default() -//! }); +//! Transform::from_xyz(2.0, 0.0, -5.0), +//! )); //! } //! ``` //! # Loading parts of a glTF asset @@ -72,18 +71,14 @@ //! }; //! *loaded = true; //! -//! commands.spawn(SceneBundle { -//! // Gets the first scene in the file -//! scene: gltf.scenes[0].clone(), -//! ..Default::default() -//! }); +//! // Spawns the first scene in the file +//! commands.spawn(SceneRoot(gltf.scenes[0].clone())); //! -//! commands.spawn(SceneBundle { -//! // Gets the scene named "Lenses_low" -//! scene: gltf.named_scenes["Lenses_low"].clone(), -//! transform: Transform::from_xyz(1.0, 2.0, 3.0), -//! ..Default::default() -//! }); +//! // Spawns the scene named "Lenses_low" +//! commands.spawn(( +//! SceneRoot(gltf.named_scenes["Lenses_low"].clone()), +//! Transform::from_xyz(1.0, 2.0, 3.0), +//! )); //! } //! ``` //! diff --git a/crates/bevy_scene/src/bundle.rs b/crates/bevy_scene/src/bundle.rs index ac656f15af93f..b0f8b38a7734f 100644 --- a/crates/bevy_scene/src/bundle.rs +++ b/crates/bevy_scene/src/bundle.rs @@ -1,4 +1,5 @@ -use bevy_asset::Handle; +#![expect(deprecated)] + use bevy_derive::{Deref, DerefMut}; use bevy_ecs::{ bundle::Bundle, @@ -11,21 +12,25 @@ use bevy_ecs::{ use bevy_render::prelude::{InheritedVisibility, ViewVisibility, Visibility}; use bevy_transform::components::{GlobalTransform, Transform}; -use crate::{DynamicScene, InstanceId, Scene, SceneSpawner}; +use crate::{DynamicSceneRoot, InstanceId, SceneRoot, SceneSpawner}; /// [`InstanceId`] of a spawned scene. It can be used with the [`SceneSpawner`] to /// interact with the spawned scene. #[derive(Component, Deref, DerefMut)] pub struct SceneInstance(pub(crate) InstanceId); -/// A component bundle for a [`Scene`] root. +/// A component bundle for a [`Scene`](crate::Scene) root. /// /// The scene from `scene` will be spawned as a child of the entity with this component. /// Once it's spawned, the entity will have a [`SceneInstance`] component. #[derive(Default, Bundle, Clone)] +#[deprecated( + since = "0.15.0", + note = "Use the `SceneRoot` component instead. Inserting `SceneRoot` will also insert the other components required by scenes automatically." +)] pub struct SceneBundle { /// Handle to the scene to spawn. - pub scene: Handle, + pub scene: SceneRoot, /// Transform of the scene root entity. pub transform: Transform, /// Global transform of the scene root entity. @@ -42,14 +47,18 @@ pub struct SceneBundle { pub view_visibility: ViewVisibility, } -/// A component bundle for a [`DynamicScene`] root. +/// A component bundle for a [`DynamicScene`](crate::DynamicScene) root. /// /// The dynamic scene from `scene` will be spawn as a child of the entity with this component. /// Once it's spawned, the entity will have a [`SceneInstance`] component. #[derive(Default, Bundle, Clone)] +#[deprecated( + since = "0.15.0", + note = "Use the `DynamicSceneRoot` component instead. Inserting `DynamicSceneRoot` will also insert the other components required by scenes automatically." +)] pub struct DynamicSceneBundle { /// Handle to the scene to spawn. - pub scene: Handle, + pub scene: DynamicSceneRoot, /// Transform of the scene root entity. pub transform: Transform, /// Global transform of the scene root entity. @@ -66,21 +75,21 @@ pub struct DynamicSceneBundle { pub view_visibility: ViewVisibility, } -/// System that will spawn scenes from [`SceneBundle`]. +/// System that will spawn scenes from the [`SceneRoot`] and [`DynamicSceneRoot`] components. pub fn scene_spawner( mut commands: Commands, mut scene_to_spawn: Query< - (Entity, &Handle, Option<&mut SceneInstance>), - (Changed>, Without>), + (Entity, &SceneRoot, Option<&mut SceneInstance>), + (Changed, Without), >, mut dynamic_scene_to_spawn: Query< - (Entity, &Handle, Option<&mut SceneInstance>), - (Changed>, Without>), + (Entity, &DynamicSceneRoot, Option<&mut SceneInstance>), + (Changed, Without), >, mut scene_spawner: ResMut, ) { for (entity, scene, instance) in &mut scene_to_spawn { - let new_instance = scene_spawner.spawn_as_child(scene.clone(), entity); + let new_instance = scene_spawner.spawn_as_child(scene.0.clone(), entity); if let Some(mut old_instance) = instance { scene_spawner.despawn_instance(**old_instance); *old_instance = SceneInstance(new_instance); @@ -89,7 +98,7 @@ pub fn scene_spawner( } } for (entity, dynamic_scene, instance) in &mut dynamic_scene_to_spawn { - let new_instance = scene_spawner.spawn_dynamic_as_child(dynamic_scene.clone(), entity); + let new_instance = scene_spawner.spawn_dynamic_as_child(dynamic_scene.0.clone(), entity); if let Some(mut old_instance) = instance { scene_spawner.despawn_instance(**old_instance); *old_instance = SceneInstance(new_instance); @@ -101,7 +110,7 @@ pub fn scene_spawner( #[cfg(test)] mod tests { - use crate::{DynamicScene, DynamicSceneBundle, ScenePlugin, SceneSpawner}; + use crate::{DynamicScene, DynamicSceneRoot, ScenePlugin, SceneSpawner}; use bevy_app::{App, ScheduleRunnerPlugin}; use bevy_asset::{AssetPlugin, Assets}; use bevy_ecs::{ @@ -111,7 +120,6 @@ mod tests { }; use bevy_hierarchy::{Children, HierarchyPlugin}; use bevy_reflect::Reflect; - use bevy_utils::default; #[derive(Component, Reflect, Default)] #[reflect(Component)] @@ -143,13 +151,10 @@ mod tests { .resource_mut::>() .add(scene); - // spawn the scene as a child of `entity` using the `DynamicSceneBundle` + // spawn the scene as a child of `entity` using `DynamicSceneRoot` let entity = app .world_mut() - .spawn(DynamicSceneBundle { - scene: scene_handle.clone(), - ..default() - }) + .spawn(DynamicSceneRoot(scene_handle.clone())) .id(); // run the app's schedule once, so that the scene gets spawned diff --git a/crates/bevy_scene/src/components.rs b/crates/bevy_scene/src/components.rs new file mode 100644 index 0000000000000..74f0f545d1d82 --- /dev/null +++ b/crates/bevy_scene/src/components.rs @@ -0,0 +1,36 @@ +use bevy_asset::Handle; +use bevy_derive::{Deref, DerefMut}; +use bevy_ecs::component::Component; +use bevy_reflect::Reflect; +use bevy_transform::components::Transform; + +#[cfg(feature = "bevy_render")] +use bevy_render::view::visibility::Visibility; + +use crate::{DynamicScene, Scene}; + +/// Adding this component will spawn the scene as a child of that entity. +/// Once it's spawned, the entity will have a [`SceneInstance`](crate::SceneInstance) component. +#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect, PartialEq, Eq)] +#[require(Transform)] +#[cfg_attr(feature = "bevy_render", require(Visibility))] +pub struct SceneRoot(pub Handle); + +impl From> for SceneRoot { + fn from(handle: Handle) -> Self { + Self(handle) + } +} + +/// Adding this component will spawn the scene as a child of that entity. +/// Once it's spawned, the entity will have a [`SceneInstance`](crate::SceneInstance) component. +#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect, PartialEq, Eq)] +#[require(Transform)] +#[cfg_attr(feature = "bevy_render", require(Visibility))] +pub struct DynamicSceneRoot(pub Handle); + +impl From> for DynamicSceneRoot { + fn from(handle: Handle) -> Self { + Self(handle) + } +} diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 48ee6493543f0..123ebf93aecb2 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -18,10 +18,7 @@ use serde::Serialize; /// Each dynamic entity in the collection contains its own run-time defined set of components. /// To spawn a dynamic scene, you can use either: /// * [`SceneSpawner::spawn_dynamic`](crate::SceneSpawner::spawn_dynamic) -/// * adding the [`DynamicSceneBundle`](crate::DynamicSceneBundle) to an entity -/// * adding the [`Handle`](bevy_asset::Handle) to an entity (the scene will only be -/// visible if the entity already has [`Transform`](bevy_transform::components::Transform) and -/// [`GlobalTransform`](bevy_transform::components::GlobalTransform) components) +/// * adding the [`DynamicSceneRoot`](crate::components::DynamicSceneRoot) component to an entity. /// * using the [`DynamicSceneBuilder`] to construct a `DynamicScene` from `World`. #[derive(Asset, TypePath, Default)] pub struct DynamicScene { diff --git a/crates/bevy_scene/src/lib.rs b/crates/bevy_scene/src/lib.rs index ffbc7af17e790..8a21b2040d78e 100644 --- a/crates/bevy_scene/src/lib.rs +++ b/crates/bevy_scene/src/lib.rs @@ -14,6 +14,7 @@ extern crate alloc; mod bundle; +mod components; mod dynamic_scene; mod dynamic_scene_builder; mod scene; @@ -29,6 +30,7 @@ pub use bevy_asset::ron; use bevy_ecs::schedule::IntoSystemConfigs; pub use bundle::*; +pub use components::*; pub use dynamic_scene::*; pub use dynamic_scene_builder::*; pub use scene::*; @@ -39,16 +41,17 @@ pub use scene_spawner::*; /// The scene prelude. /// /// This includes the most common types in this crate, re-exported for your convenience. +#[expect(deprecated)] pub mod prelude { #[doc(hidden)] pub use crate::{ - DynamicScene, DynamicSceneBuilder, DynamicSceneBundle, Scene, SceneBundle, SceneFilter, - SceneSpawner, + DynamicScene, DynamicSceneBuilder, DynamicSceneBundle, DynamicSceneRoot, Scene, + SceneBundle, SceneFilter, SceneRoot, SceneSpawner, }; } use bevy_app::prelude::*; -use bevy_asset::{AssetApp, Handle}; +use bevy_asset::AssetApp; /// Plugin that provides scene functionality to an [`App`]. #[derive(Default)] @@ -61,13 +64,15 @@ impl Plugin for ScenePlugin { .init_asset::() .init_asset_loader::() .init_resource::() + .register_type::() + .register_type::() .add_systems(SpawnScene, (scene_spawner, scene_spawner_system).chain()); - // Register component hooks for DynamicScene + // Register component hooks for DynamicSceneRoot app.world_mut() - .register_component_hooks::>() + .register_component_hooks::() .on_remove(|mut world, entity, _| { - let Some(handle) = world.get::>(entity) else { + let Some(handle) = world.get::(entity) else { return; }; let id = handle.id(); @@ -82,9 +87,9 @@ impl Plugin for ScenePlugin { } }); - // Register component hooks for Scene + // Register component hooks for SceneRoot app.world_mut() - .register_component_hooks::>() + .register_component_hooks::() .on_remove(|mut world, entity, _| { if let Some(&SceneInstance(scene_instance)) = world.get::(entity) { let Some(mut scene_spawner) = world.get_resource_mut::() else { diff --git a/crates/bevy_scene/src/scene.rs b/crates/bevy_scene/src/scene.rs index f3a44bf666c3c..961f056a193dd 100644 --- a/crates/bevy_scene/src/scene.rs +++ b/crates/bevy_scene/src/scene.rs @@ -9,10 +9,7 @@ use bevy_reflect::{PartialReflect, TypePath}; /// To spawn a scene, you can use either: /// * [`SceneSpawner::spawn`](crate::SceneSpawner::spawn) -/// * adding the [`SceneBundle`](crate::SceneBundle) to an entity -/// * adding the [`Handle`](bevy_asset::Handle) to an entity (the scene will only be -/// visible if the entity already has [`Transform`](bevy_transform::components::Transform) and -/// [`GlobalTransform`](bevy_transform::components::GlobalTransform) components) +/// * adding the [`SceneRoot`](crate::components::SceneRoot) component to an entity. #[derive(Asset, TypePath, Debug)] pub struct Scene { /// The world of the scene, containing its entities and resources. diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index cd138502251bf..b354b52b09175 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -482,7 +482,7 @@ mod tests { }; use bevy_reflect::Reflect; - use crate::{DynamicSceneBuilder, ScenePlugin}; + use crate::{DynamicSceneBuilder, DynamicSceneRoot, ScenePlugin}; use super::*; @@ -725,7 +725,8 @@ mod tests { // Spawn scene. for _ in 0..count { - app.world_mut().spawn((ComponentA, scene.clone())); + app.world_mut() + .spawn((ComponentA, DynamicSceneRoot(scene.clone()))); } app.update(); diff --git a/examples/3d/anisotropy.rs b/examples/3d/anisotropy.rs index d5d42123e791a..c7b92e0eec801 100644 --- a/examples/3d/anisotropy.rs +++ b/examples/3d/anisotropy.rs @@ -72,11 +72,10 @@ fn setup(mut commands: Commands, asset_server: Res, app_status: Res spawn_directional_light(&mut commands); - commands.spawn(SceneBundle { - scene: asset_server.load("models/AnisotropyBarnLamp/AnisotropyBarnLamp.gltf#Scene0"), - transform: Transform::from_xyz(0.0, 0.07, -0.13), - ..default() - }); + commands.spawn(( + SceneRoot(asset_server.load("models/AnisotropyBarnLamp/AnisotropyBarnLamp.gltf#Scene0")), + Transform::from_xyz(0.0, 0.07, -0.13), + )); spawn_text(&mut commands, &app_status); } diff --git a/examples/3d/anti_aliasing.rs b/examples/3d/anti_aliasing.rs index a3dfad95480e6..2f51112c22dc8 100644 --- a/examples/3d/anti_aliasing.rs +++ b/examples/3d/anti_aliasing.rs @@ -272,11 +272,9 @@ fn setup( } // Flight Helmet - commands.spawn(SceneBundle { - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), - ..default() - }); + commands.spawn(SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf"), + ))); // Light commands.spawn(( diff --git a/examples/3d/atmospheric_fog.rs b/examples/3d/atmospheric_fog.rs index b6696cc5d5bb6..43f2ce4fc81c4 100644 --- a/examples/3d/atmospheric_fog.rs +++ b/examples/3d/atmospheric_fog.rs @@ -69,11 +69,9 @@ fn setup_terrain_scene( )); // Terrain - commands.spawn(SceneBundle { - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/terrain/Mountains.gltf")), - ..default() - }); + commands.spawn(SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/terrain/Mountains.gltf"), + ))); // Sky commands.spawn(( diff --git a/examples/3d/clearcoat.rs b/examples/3d/clearcoat.rs index 49f59b7d26098..80194dbe61f26 100644 --- a/examples/3d/clearcoat.rs +++ b/examples/3d/clearcoat.rs @@ -145,14 +145,13 @@ fn spawn_coated_glass_bubble_sphere( /// This object is in glTF format, using the `KHR_materials_clearcoat` /// extension. fn spawn_golf_ball(commands: &mut Commands, asset_server: &AssetServer) { - commands - .spawn(SceneBundle { - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/GolfBall/GolfBall.glb")), - transform: Transform::from_xyz(1.0, 1.0, 0.0).with_scale(Vec3::splat(SPHERE_SCALE)), - ..default() - }) - .insert(ExampleSphere); + commands.spawn(( + SceneRoot( + asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/GolfBall/GolfBall.glb")), + ), + Transform::from_xyz(1.0, 1.0, 0.0).with_scale(Vec3::splat(SPHERE_SCALE)), + ExampleSphere, + )); } /// Spawns an object with only a clearcoat normal map (a scratch pattern) and no diff --git a/examples/3d/color_grading.rs b/examples/3d/color_grading.rs index cb16ad5a7bdd2..d40225f2d3e9c 100644 --- a/examples/3d/color_grading.rs +++ b/examples/3d/color_grading.rs @@ -381,21 +381,18 @@ fn add_camera(commands: &mut Commands, asset_server: &AssetServer, color_grading fn add_basic_scene(commands: &mut Commands, asset_server: &AssetServer) { // Spawn the main scene. - commands.spawn(SceneBundle { - scene: asset_server.load( - GltfAssetLabel::Scene(0).from_asset("models/TonemappingTest/TonemappingTest.gltf"), - ), - ..default() - }); + commands.spawn(SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/TonemappingTest/TonemappingTest.gltf"), + ))); // Spawn the flight helmet. - commands.spawn(SceneBundle { - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), - transform: Transform::from_xyz(0.5, 0.0, -0.5) - .with_rotation(Quat::from_rotation_y(-0.15 * PI)), - ..default() - }); + commands.spawn(( + SceneRoot( + asset_server + .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), + ), + Transform::from_xyz(0.5, 0.0, -0.5).with_rotation(Quat::from_rotation_y(-0.15 * PI)), + )); // Spawn the light. commands.spawn(( diff --git a/examples/3d/deferred_rendering.rs b/examples/3d/deferred_rendering.rs index eed65ebd5ecb3..abdcd2da187c9 100644 --- a/examples/3d/deferred_rendering.rs +++ b/examples/3d/deferred_rendering.rs @@ -85,15 +85,11 @@ fn setup( let helmet_scene = asset_server .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")); - commands.spawn(SceneBundle { - scene: helmet_scene.clone(), - ..default() - }); - commands.spawn(SceneBundle { - scene: helmet_scene, - transform: Transform::from_xyz(-4.0, 0.0, -3.0), - ..default() - }); + commands.spawn(SceneRoot(helmet_scene.clone())); + commands.spawn(( + SceneRoot(helmet_scene), + Transform::from_xyz(-4.0, 0.0, -3.0), + )); let mut forward_mat: StandardMaterial = Color::srgb(0.1, 0.2, 0.1).into(); forward_mat.opaque_render_method = OpaqueRendererMethod::Forward; diff --git a/examples/3d/depth_of_field.rs b/examples/3d/depth_of_field.rs index cbcffcd42a001..fb8c2282ed088 100644 --- a/examples/3d/depth_of_field.rs +++ b/examples/3d/depth_of_field.rs @@ -88,13 +88,9 @@ fn setup(mut commands: Commands, asset_server: Res, app_settings: R } // Spawn the scene. - commands.spawn(SceneBundle { - scene: asset_server.load( - GltfAssetLabel::Scene(0) - .from_asset("models/DepthOfFieldExample/DepthOfFieldExample.glb"), - ), - ..default() - }); + commands.spawn(SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/DepthOfFieldExample/DepthOfFieldExample.glb"), + ))); // Spawn the help text. commands.spawn( diff --git a/examples/3d/irradiance_volumes.rs b/examples/3d/irradiance_volumes.rs index fb24eea021044..77612d11d7524 100644 --- a/examples/3d/irradiance_volumes.rs +++ b/examples/3d/irradiance_volumes.rs @@ -227,10 +227,7 @@ fn setup(mut commands: Commands, assets: Res, app_status: Res>, mut app_status: ResMut, - mut sphere_query: Query< - &mut Visibility, - (With, With, Without>), - >, - mut fox_query: Query<&mut Visibility, (With, With>)>, + mut sphere_query: Query<&mut Visibility, (With, With, Without)>, + mut fox_query: Query<&mut Visibility, (With, With)>, ) { if !keyboard.just_pressed(KeyCode::Tab) { return; diff --git a/examples/3d/lightmaps.rs b/examples/3d/lightmaps.rs index 5c2f8b47676b2..c77d0c72c24e5 100644 --- a/examples/3d/lightmaps.rs +++ b/examples/3d/lightmaps.rs @@ -12,11 +12,9 @@ fn main() { } fn setup(mut commands: Commands, asset_server: Res) { - commands.spawn(SceneBundle { - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/CornellBox/CornellBox.glb")), - ..default() - }); + commands.spawn(SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/CornellBox/CornellBox.glb"), + ))); commands.spawn(Camera3dBundle { transform: Transform::from_xyz(-278.0, 273.0, 800.0), diff --git a/examples/3d/load_gltf.rs b/examples/3d/load_gltf.rs index 5b87b3cd1af75..07d7e3a99a00a 100644 --- a/examples/3d/load_gltf.rs +++ b/examples/3d/load_gltf.rs @@ -46,11 +46,9 @@ fn setup(mut commands: Commands, asset_server: Res) { } .build(), )); - commands.spawn(SceneBundle { - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), - ..default() - }); + commands.spawn(SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf"), + ))); } fn animate_light_direction( diff --git a/examples/3d/load_gltf_extras.rs b/examples/3d/load_gltf_extras.rs index 7291a31927194..250c230e71cb3 100644 --- a/examples/3d/load_gltf_extras.rs +++ b/examples/3d/load_gltf_extras.rs @@ -28,11 +28,9 @@ fn setup(mut commands: Commands, asset_server: Res) { }); // a barebones scene containing one of each gltf_extra type - commands.spawn(SceneBundle { - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/extras/gltf_extras.glb")), - ..default() - }); + commands.spawn(SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/extras/gltf_extras.glb"), + ))); // a place to display the extras on screen commands.spawn(( diff --git a/examples/3d/pcss.rs b/examples/3d/pcss.rs index 3c073461f25aa..686fdc66f59b6 100644 --- a/examples/3d/pcss.rs +++ b/examples/3d/pcss.rs @@ -205,10 +205,9 @@ fn spawn_light(commands: &mut Commands, app_status: &AppStatus) { /// Loads and spawns the glTF palm tree scene. fn spawn_gltf_scene(commands: &mut Commands, asset_server: &AssetServer) { - commands.spawn(SceneBundle { - scene: asset_server.load("models/PalmTree/PalmTree.gltf#Scene0"), - ..default() - }); + commands.spawn(SceneRoot( + asset_server.load("models/PalmTree/PalmTree.gltf#Scene0"), + )); } /// Spawns all the buttons at the bottom of the screen. diff --git a/examples/3d/post_processing.rs b/examples/3d/post_processing.rs index 3472f0294fcfa..8e033c0acf713 100644 --- a/examples/3d/post_processing.rs +++ b/examples/3d/post_processing.rs @@ -93,21 +93,18 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) { /// variety of colors. fn spawn_scene(commands: &mut Commands, asset_server: &AssetServer) { // Spawn the main scene. - commands.spawn(SceneBundle { - scene: asset_server.load( - GltfAssetLabel::Scene(0).from_asset("models/TonemappingTest/TonemappingTest.gltf"), - ), - ..default() - }); + commands.spawn(SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/TonemappingTest/TonemappingTest.gltf"), + ))); // Spawn the flight helmet. - commands.spawn(SceneBundle { - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), - transform: Transform::from_xyz(0.5, 0.0, -0.5) - .with_rotation(Quat::from_rotation_y(-0.15 * PI)), - ..default() - }); + commands.spawn(( + SceneRoot( + asset_server + .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), + ), + Transform::from_xyz(0.5, 0.0, -0.5).with_rotation(Quat::from_rotation_y(-0.15 * PI)), + )); // Spawn the light. commands.spawn(( diff --git a/examples/3d/query_gltf_primitives.rs b/examples/3d/query_gltf_primitives.rs index 725c4321b84e3..9a58e74b9c082 100644 --- a/examples/3d/query_gltf_primitives.rs +++ b/examples/3d/query_gltf_primitives.rs @@ -83,13 +83,13 @@ fn setup(mut commands: Commands, asset_server: Res) { } .build(), )); - commands.spawn(SceneBundle { - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/GltfPrimitives/gltf_primitives.glb")), - transform: Transform { + commands.spawn(( + SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/GltfPrimitives/gltf_primitives.glb"), + )), + Transform { rotation: Quat::from_rotation_y(-90.0 / 180.0 * PI), ..default() }, - ..default() - }); + )); } diff --git a/examples/3d/reflection_probes.rs b/examples/3d/reflection_probes.rs index 25c0aead9d3c2..1a4fd3cfe4cad 100644 --- a/examples/3d/reflection_probes.rs +++ b/examples/3d/reflection_probes.rs @@ -96,10 +96,9 @@ fn setup( // Spawns the cubes, light, and camera. fn spawn_scene(commands: &mut Commands, asset_server: &AssetServer) { - commands.spawn(SceneBundle { - scene: asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/cubes/Cubes.glb")), - ..SceneBundle::default() - }); + commands.spawn(SceneRoot( + asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/cubes/Cubes.glb")), + )); } // Spawns the camera. diff --git a/examples/3d/split_screen.rs b/examples/3d/split_screen.rs index eaaa37f459473..95b6ac52c5f18 100644 --- a/examples/3d/split_screen.rs +++ b/examples/3d/split_screen.rs @@ -27,10 +27,9 @@ fn setup( MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))), )); - commands.spawn(SceneBundle { - scene: asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")), - ..default() - }); + commands.spawn(SceneRoot( + asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")), + )); // Light commands.spawn(( diff --git a/examples/3d/ssr.rs b/examples/3d/ssr.rs index 09c28f6942d4b..08f09ff288aa2 100644 --- a/examples/3d/ssr.rs +++ b/examples/3d/ssr.rs @@ -163,15 +163,15 @@ fn spawn_cube( // Spawns the flight helmet. fn spawn_flight_helmet(commands: &mut Commands, asset_server: &AssetServer) { - commands - .spawn(SceneBundle { - scene: asset_server + commands.spawn(( + SceneRoot( + asset_server .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), - transform: Transform::from_scale(Vec3::splat(2.5)), - ..default() - }) - .insert(FlightHelmetModel) - .insert(Visibility::Hidden); + ), + Transform::from_scale(Vec3::splat(2.5)), + FlightHelmetModel, + Visibility::Hidden, + )); } // Spawns the water plane. diff --git a/examples/3d/tonemapping.rs b/examples/3d/tonemapping.rs index f5709c65aa389..aa27c822b1646 100644 --- a/examples/3d/tonemapping.rs +++ b/examples/3d/tonemapping.rs @@ -95,24 +95,20 @@ fn setup( fn setup_basic_scene(mut commands: Commands, asset_server: Res) { // Main scene - commands - .spawn(SceneBundle { - scene: asset_server.load( - GltfAssetLabel::Scene(0).from_asset("models/TonemappingTest/TonemappingTest.gltf"), - ), - ..default() - }) - .insert(SceneNumber(1)); + commands.spawn(( + SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/TonemappingTest/TonemappingTest.gltf"), + )), + SceneNumber(1), + )); // Flight Helmet commands.spawn(( - SceneBundle { - scene: asset_server + SceneRoot( + asset_server .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), - transform: Transform::from_xyz(0.5, 0.0, -0.5) - .with_rotation(Quat::from_rotation_y(-0.15 * PI)), - ..default() - }, + ), + Transform::from_xyz(0.5, 0.0, -0.5).with_rotation(Quat::from_rotation_y(-0.15 * PI)), SceneNumber(1), )); diff --git a/examples/3d/update_gltf_scene.rs b/examples/3d/update_gltf_scene.rs index c7bda9db8b917..ac9df29e6d909 100644 --- a/examples/3d/update_gltf_scene.rs +++ b/examples/3d/update_gltf_scene.rs @@ -38,20 +38,20 @@ fn setup(mut commands: Commands, asset_server: Res) { )); // Spawn the scene as a child of this entity at the given transform - commands.spawn(SceneBundle { - transform: Transform::from_xyz(-1.0, 0.0, 0.0), - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), - ..default() - }); + commands.spawn(( + Transform::from_xyz(-1.0, 0.0, 0.0), + SceneRoot( + asset_server + .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), + ), + )); // Spawn a second scene, and add a tag component to be able to target it later commands.spawn(( - SceneBundle { - scene: asset_server + SceneRoot( + asset_server .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), - ..default() - }, + ), MovedScene, )); } diff --git a/examples/3d/visibility_range.rs b/examples/3d/visibility_range.rs index f4de18cc4c622..b237d1301d24f 100644 --- a/examples/3d/visibility_range.rs +++ b/examples/3d/visibility_range.rs @@ -101,23 +101,23 @@ fn setup( // Spawn the two HLODs. - commands - .spawn(SceneBundle { - scene: asset_server + commands.spawn(( + SceneRoot( + asset_server .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")), - ..default() - }) - .insert(MainModel::HighPoly); + ), + MainModel::HighPoly, + )); - commands - .spawn(SceneBundle { - scene: asset_server.load( + commands.spawn(( + SceneRoot( + asset_server.load( GltfAssetLabel::Scene(0) .from_asset("models/FlightHelmetLowPoly/FlightHelmetLowPoly.gltf"), ), - ..default() - }) - .insert(MainModel::LowPoly); + ), + MainModel::LowPoly, + )); // Spawn a light. commands.spawn(( diff --git a/examples/3d/volumetric_fog.rs b/examples/3d/volumetric_fog.rs index da799c56139de..b100ebc923484 100644 --- a/examples/3d/volumetric_fog.rs +++ b/examples/3d/volumetric_fog.rs @@ -57,13 +57,9 @@ fn main() { /// Initializes the scene. fn setup(mut commands: Commands, asset_server: Res, app_settings: Res) { // Spawn the glTF scene. - commands.spawn(SceneBundle { - scene: asset_server.load( - GltfAssetLabel::Scene(0) - .from_asset("models/VolumetricFogExample/VolumetricFogExample.glb"), - ), - ..default() - }); + commands.spawn(SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/VolumetricFogExample/VolumetricFogExample.glb"), + ))); // Spawn the camera. commands diff --git a/examples/animation/animated_fox.rs b/examples/animation/animated_fox.rs index 947cc93815b7f..73a662526e190 100644 --- a/examples/animation/animated_fox.rs +++ b/examples/animation/animated_fox.rs @@ -80,10 +80,9 @@ fn setup( )); // Fox - commands.spawn(SceneBundle { - scene: asset_server.load(GltfAssetLabel::Scene(0).from_asset(FOX_PATH)), - ..default() - }); + commands.spawn(SceneRoot( + asset_server.load(GltfAssetLabel::Scene(0).from_asset(FOX_PATH)), + )); println!("Animation controls:"); println!(" - spacebar: play / pause"); diff --git a/examples/animation/animation_graph.rs b/examples/animation/animation_graph.rs index 1141d44c1aeb5..1d44da5105af3 100644 --- a/examples/animation/animation_graph.rs +++ b/examples/animation/animation_graph.rs @@ -232,11 +232,12 @@ fn setup_scene( Transform::from_xyz(-4.0, 8.0, 13.0), )); - commands.spawn(SceneBundle { - scene: asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")), - transform: Transform::from_scale(Vec3::splat(0.07)), - ..default() - }); + commands.spawn(( + SceneRoot( + asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")), + ), + Transform::from_scale(Vec3::splat(0.07)), + )); // Ground diff --git a/examples/animation/animation_masks.rs b/examples/animation/animation_masks.rs index 112554d075795..203fb8ce9c0ed 100644 --- a/examples/animation/animation_masks.rs +++ b/examples/animation/animation_masks.rs @@ -118,11 +118,12 @@ fn setup_scene( )); // Spawn the fox. - commands.spawn(SceneBundle { - scene: asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")), - transform: Transform::from_scale(Vec3::splat(0.07)), - ..default() - }); + commands.spawn(( + SceneRoot( + asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")), + ), + Transform::from_scale(Vec3::splat(0.07)), + )); // Spawn the ground. commands.spawn(( diff --git a/examples/animation/gltf_skinned_mesh.rs b/examples/animation/gltf_skinned_mesh.rs index 0181a7bdef0c9..d4568f3482fd9 100644 --- a/examples/animation/gltf_skinned_mesh.rs +++ b/examples/animation/gltf_skinned_mesh.rs @@ -26,11 +26,9 @@ fn setup(mut commands: Commands, asset_server: Res) { }); // Spawn the first scene in `models/SimpleSkin/SimpleSkin.gltf` - commands.spawn(SceneBundle { - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/SimpleSkin/SimpleSkin.gltf")), - ..default() - }); + commands.spawn(SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/SimpleSkin/SimpleSkin.gltf"), + ))); } /// The scene hierarchy currently looks somewhat like this: diff --git a/examples/animation/morph_targets.rs b/examples/animation/morph_targets.rs index 001bfa1fda18f..57e612c17221e 100644 --- a/examples/animation/morph_targets.rs +++ b/examples/animation/morph_targets.rs @@ -46,11 +46,9 @@ fn setup(asset_server: Res, mut commands: Commands) { .from_asset("models/animated/MorphStressTest.gltf"), ), }); - commands.spawn(SceneBundle { - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/animated/MorphStressTest.gltf")), - ..default() - }); + commands.spawn(SceneRoot(asset_server.load( + GltfAssetLabel::Scene(0).from_asset("models/animated/MorphStressTest.gltf"), + ))); commands.spawn(( DirectionalLight::default(), Transform::from_rotation(Quat::from_rotation_z(PI / 2.0)), diff --git a/examples/asset/hot_asset_reloading.rs b/examples/asset/hot_asset_reloading.rs index 4e012a76c5e9e..eaa5b5a890dbb 100644 --- a/examples/asset/hot_asset_reloading.rs +++ b/examples/asset/hot_asset_reloading.rs @@ -23,10 +23,7 @@ fn setup(mut commands: Commands, asset_server: Res) { // You should see the changes immediately show up in your app. // mesh - commands.spawn(SceneBundle { - scene: scene_handle, - ..default() - }); + commands.spawn(SceneRoot(scene_handle)); // light commands.spawn(( DirectionalLight::default(), diff --git a/examples/asset/multi_asset_sync.rs b/examples/asset/multi_asset_sync.rs index b96e3ae6cb3e4..792688a7e787a 100644 --- a/examples/asset/multi_asset_sync.rs +++ b/examples/asset/multi_asset_sync.rs @@ -261,11 +261,7 @@ fn wait_on_load( // All gltfs must exist because this is guarded by the `AssetBarrier`. let gltf = gltfs.get(&foxes.0[index]).unwrap(); let scene = gltf.scenes.first().unwrap().clone(); - commands.spawn(SceneBundle { - scene, - transform: Transform::from_translation(position), - ..Default::default() - }); + commands.spawn((SceneRoot(scene), Transform::from_translation(position))); } } } diff --git a/examples/camera/projection_zoom.rs b/examples/camera/projection_zoom.rs index e5ab7a12c1b54..0a2d3e854b290 100644 --- a/examples/camera/projection_zoom.rs +++ b/examples/camera/projection_zoom.rs @@ -78,14 +78,12 @@ fn setup( commands.spawn(( Name::new("Fox"), - SceneBundle { - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")), - // Note: the scale adjustment is purely an accident of our fox model, which renders - // HUGE unless mitigated! - transform: Transform::from_translation(Vec3::splat(0.0)).with_scale(Vec3::splat(0.025)), - ..default() - }, + SceneRoot( + asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")), + ), + // Note: the scale adjustment is purely an accident of our fox model, which renders + // HUGE unless mitigated! + Transform::from_translation(Vec3::splat(0.0)).with_scale(Vec3::splat(0.025)), )); commands.spawn(( diff --git a/examples/games/alien_cake_addict.rs b/examples/games/alien_cake_addict.rs index 3fcddf9289b97..4345582eaf915 100644 --- a/examples/games/alien_cake_addict.rs +++ b/examples/games/alien_cake_addict.rs @@ -139,11 +139,10 @@ fn setup(mut commands: Commands, asset_server: Res, mut game: ResMu (0..BOARD_SIZE_I) .map(|i| { let height = rng.gen_range(-0.1..0.1); - commands.spawn(SceneBundle { - transform: Transform::from_xyz(i as f32, height - 0.2, j as f32), - scene: cell_scene.clone(), - ..default() - }); + commands.spawn(( + Transform::from_xyz(i as f32, height - 0.2, j as f32), + SceneRoot(cell_scene.clone()), + )); Cell { height } }) .collect() @@ -153,8 +152,8 @@ fn setup(mut commands: Commands, asset_server: Res, mut game: ResMu // spawn the game character game.player.entity = Some( commands - .spawn(SceneBundle { - transform: Transform { + .spawn(( + Transform { translation: Vec3::new( game.player.i as f32, game.board[game.player.j][game.player.i].height, @@ -163,10 +162,11 @@ fn setup(mut commands: Commands, asset_server: Res, mut game: ResMu rotation: Quat::from_rotation_y(-PI / 2.), ..default() }, - scene: asset_server - .load(GltfAssetLabel::Scene(0).from_asset("models/AlienCake/alien.glb")), - ..default() - }) + SceneRoot( + asset_server + .load(GltfAssetLabel::Scene(0).from_asset("models/AlienCake/alien.glb")), + ), + )) .id(), ); @@ -345,15 +345,14 @@ fn spawn_bonus( } game.bonus.entity = Some( commands - .spawn(SceneBundle { - transform: Transform::from_xyz( + .spawn(( + Transform::from_xyz( game.bonus.i as f32, game.board[game.bonus.j][game.bonus.i].height + 0.2, game.bonus.j as f32, ), - scene: game.bonus.handle.clone(), - ..default() - }) + SceneRoot(game.bonus.handle.clone()), + )) .with_child(( PointLight { color: Color::srgb(1.0, 1.0, 0.0), diff --git a/examples/games/loading_screen.rs b/examples/games/loading_screen.rs index 48d15e01a5d08..16d2bfc8c928e 100644 --- a/examples/games/loading_screen.rs +++ b/examples/games/loading_screen.rs @@ -154,11 +154,8 @@ fn load_level_1( loading_data.loading_assets.push(fox.clone().into()); // Spawn the fox. commands.spawn(( - SceneBundle { - scene: fox.clone(), - transform: Transform::from_xyz(0.0, 0.0, 0.0), - ..default() - }, + SceneRoot(fox.clone()), + Transform::from_xyz(0.0, 0.0, 0.0), LevelComponents, )); @@ -194,13 +191,7 @@ fn load_level_2( loading_data .loading_assets .push(helmet_scene.clone().into()); - commands.spawn(( - SceneBundle { - scene: helmet_scene.clone(), - ..default() - }, - LevelComponents, - )); + commands.spawn((SceneRoot(helmet_scene.clone()), LevelComponents)); // Spawn the light. commands.spawn(( diff --git a/examples/scene/scene.rs b/examples/scene/scene.rs index 1316a0a5c0b9a..379f36fcd90ec 100644 --- a/examples/scene/scene.rs +++ b/examples/scene/scene.rs @@ -65,13 +65,10 @@ const SCENE_FILE_PATH: &str = "scenes/load_scene_example.scn.ron"; const NEW_SCENE_FILE_PATH: &str = "scenes/load_scene_example-new.scn.ron"; fn load_scene_system(mut commands: Commands, asset_server: Res) { - // "Spawning" a scene bundle creates a new entity and spawns new instances + // Spawning a DynamicSceneRoot creates a new entity and spawns new instances // of the given scene's entities as children of that entity. - commands.spawn(DynamicSceneBundle { - // Scenes are loaded just like any other asset. - scene: asset_server.load(SCENE_FILE_PATH), - ..default() - }); + // Scenes can be loaded just like any other asset. + commands.spawn(DynamicSceneRoot(asset_server.load(SCENE_FILE_PATH))); } // This system logs all ComponentA components in our world. Try making a change to a ComponentA in diff --git a/examples/stress_tests/many_foxes.rs b/examples/stress_tests/many_foxes.rs index f25cef94913f3..f904351f282ae 100644 --- a/examples/stress_tests/many_foxes.rs +++ b/examples/stress_tests/many_foxes.rs @@ -172,13 +172,12 @@ fn setup( let (x, z) = (radius * c, radius * s); commands.entity(ring_parent).with_children(|builder| { - builder.spawn(SceneBundle { - scene: fox_handle.clone(), - transform: Transform::from_xyz(x, 0.0, z) + builder.spawn(( + SceneRoot(fox_handle.clone()), + Transform::from_xyz(x, 0.0, z) .with_scale(Vec3::splat(0.01)) .with_rotation(base_rotation * Quat::from_rotation_y(-fox_angle)), - ..default() - }); + )); }); } diff --git a/examples/transforms/align.rs b/examples/transforms/align.rs index 7483547bcb30c..a1301e9bacc1d 100644 --- a/examples/transforms/align.rs +++ b/examples/transforms/align.rs @@ -81,11 +81,10 @@ fn setup( // Finally, our ship that is going to rotate commands.spawn(( - SceneBundle { - scene: asset_server + SceneRoot( + asset_server .load(GltfAssetLabel::Scene(0).from_asset("models/ship/craft_speederD.gltf")), - ..default() - }, + ), Ship { target_transform: random_axes_target_alignment(&RandomAxes(first, second)), ..default() diff --git a/examples/window/multiple_windows.rs b/examples/window/multiple_windows.rs index 40b120570f8d8..b4a6e36bcad41 100644 --- a/examples/window/multiple_windows.rs +++ b/examples/window/multiple_windows.rs @@ -12,10 +12,9 @@ fn main() { fn setup_scene(mut commands: Commands, asset_server: Res) { // add entities to the world - commands.spawn(SceneBundle { - scene: asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/torus/torus.gltf")), - ..default() - }); + commands.spawn(SceneRoot( + asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/torus/torus.gltf")), + )); // light commands.spawn(( DirectionalLight::default(),