
# 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<Scene>` and `Handle<DynamicScene>` 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), )); ```
108 lines
3.5 KiB
Rust
108 lines
3.5 KiB
Rust
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
|
#![forbid(unsafe_code)]
|
|
#![doc(
|
|
html_logo_url = "https://bevyengine.org/assets/icon.png",
|
|
html_favicon_url = "https://bevyengine.org/assets/icon.png"
|
|
)]
|
|
|
|
//! Provides scene definition, instantiation and serialization/deserialization.
|
|
//!
|
|
//! Scenes are collections of entities and their associated components that can be
|
|
//! instantiated or removed from a world to allow composition. Scenes can be serialized/deserialized,
|
|
//! for example to save part of the world state to a file.
|
|
|
|
extern crate alloc;
|
|
|
|
mod bundle;
|
|
mod components;
|
|
mod dynamic_scene;
|
|
mod dynamic_scene_builder;
|
|
mod scene;
|
|
mod scene_filter;
|
|
mod scene_loader;
|
|
mod scene_spawner;
|
|
|
|
#[cfg(feature = "serialize")]
|
|
pub mod serde;
|
|
|
|
/// Rusty Object Notation, a crate used to serialize and deserialize bevy scenes.
|
|
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::*;
|
|
pub use scene_filter::*;
|
|
pub use scene_loader::*;
|
|
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, DynamicSceneRoot, Scene,
|
|
SceneBundle, SceneFilter, SceneRoot, SceneSpawner,
|
|
};
|
|
}
|
|
|
|
use bevy_app::prelude::*;
|
|
use bevy_asset::AssetApp;
|
|
|
|
/// Plugin that provides scene functionality to an [`App`].
|
|
#[derive(Default)]
|
|
pub struct ScenePlugin;
|
|
|
|
#[cfg(feature = "serialize")]
|
|
impl Plugin for ScenePlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.init_asset::<DynamicScene>()
|
|
.init_asset::<Scene>()
|
|
.init_asset_loader::<SceneLoader>()
|
|
.init_resource::<SceneSpawner>()
|
|
.register_type::<SceneRoot>()
|
|
.register_type::<DynamicSceneRoot>()
|
|
.add_systems(SpawnScene, (scene_spawner, scene_spawner_system).chain());
|
|
|
|
// Register component hooks for DynamicSceneRoot
|
|
app.world_mut()
|
|
.register_component_hooks::<DynamicSceneRoot>()
|
|
.on_remove(|mut world, entity, _| {
|
|
let Some(handle) = world.get::<DynamicSceneRoot>(entity) else {
|
|
return;
|
|
};
|
|
let id = handle.id();
|
|
if let Some(&SceneInstance(scene_instance)) = world.get::<SceneInstance>(entity) {
|
|
let Some(mut scene_spawner) = world.get_resource_mut::<SceneSpawner>() else {
|
|
return;
|
|
};
|
|
if let Some(instance_ids) = scene_spawner.spawned_dynamic_scenes.get_mut(&id) {
|
|
instance_ids.remove(&scene_instance);
|
|
}
|
|
scene_spawner.despawn_instance(scene_instance);
|
|
}
|
|
});
|
|
|
|
// Register component hooks for SceneRoot
|
|
app.world_mut()
|
|
.register_component_hooks::<SceneRoot>()
|
|
.on_remove(|mut world, entity, _| {
|
|
if let Some(&SceneInstance(scene_instance)) = world.get::<SceneInstance>(entity) {
|
|
let Some(mut scene_spawner) = world.get_resource_mut::<SceneSpawner>() else {
|
|
return;
|
|
};
|
|
scene_spawner.despawn_instance(scene_instance);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
#[cfg(not(feature = "serialize"))]
|
|
impl Plugin for ScenePlugin {
|
|
fn build(&self, _: &mut App) {}
|
|
}
|