mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 12:43:34 +00:00
Finish documenting bevy_scene
(#9949)
# Objective Finish documenting `bevy_scene`. ## Solution Document the remaining items and add a crate-level `warn(missing_doc)` attribute as for the other crates with completed documentation.
This commit is contained in:
parent
a1a81e5721
commit
ec34fe01d1
7 changed files with 164 additions and 7 deletions
|
@ -24,15 +24,20 @@ pub struct SceneInstance(InstanceId);
|
|||
/// Once it's spawned, the entity will have a [`SceneInstance`] component.
|
||||
#[derive(Default, Bundle)]
|
||||
pub struct SceneBundle {
|
||||
/// Handle to the scene to spawn
|
||||
/// Handle to the scene to spawn.
|
||||
pub scene: Handle<Scene>,
|
||||
/// Transform of the scene root entity.
|
||||
pub transform: Transform,
|
||||
/// Global transform of the scene root entity.
|
||||
pub global_transform: GlobalTransform,
|
||||
|
||||
/// User-driven visibility of the scene root entity.
|
||||
#[cfg(feature = "bevy_render")]
|
||||
pub visibility: Visibility,
|
||||
/// Inherited visibility of the scene root entity.
|
||||
#[cfg(feature = "bevy_render")]
|
||||
pub inherited_visibility: InheritedVisibility,
|
||||
/// Algorithmically-computed visibility of the scene root entity for rendering.
|
||||
#[cfg(feature = "bevy_render")]
|
||||
pub view_visibility: ViewVisibility,
|
||||
}
|
||||
|
@ -43,15 +48,20 @@ pub struct SceneBundle {
|
|||
/// Once it's spawned, the entity will have a [`SceneInstance`] component.
|
||||
#[derive(Default, Bundle)]
|
||||
pub struct DynamicSceneBundle {
|
||||
/// Handle to the scene to spawn
|
||||
/// Handle to the scene to spawn.
|
||||
pub scene: Handle<DynamicScene>,
|
||||
/// Transform of the scene root entity.
|
||||
pub transform: Transform,
|
||||
/// Global transform of the scene root entity.
|
||||
pub global_transform: GlobalTransform,
|
||||
|
||||
/// User-driven visibility of the scene root entity.
|
||||
#[cfg(feature = "bevy_render")]
|
||||
pub visibility: Visibility,
|
||||
/// Inherited visibility of the scene root entity.
|
||||
#[cfg(feature = "bevy_render")]
|
||||
pub inherited_visibility: InheritedVisibility,
|
||||
/// Algorithmically-computed visibility of the scene root entity for rendering.
|
||||
#[cfg(feature = "bevy_render")]
|
||||
pub view_visibility: ViewVisibility,
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@ use serde::Serialize;
|
|||
/// [`GlobalTransform`](bevy_transform::components::GlobalTransform) components)
|
||||
#[derive(Asset, TypePath, Default)]
|
||||
pub struct DynamicScene {
|
||||
/// Resources stored in the dynamic scene.
|
||||
pub resources: Vec<Box<dyn Reflect>>,
|
||||
/// Entities contained in the dynamic scene.
|
||||
pub entities: Vec<DynamicEntity>,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
//! 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.
|
||||
|
||||
#![allow(clippy::type_complexity)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
mod bundle;
|
||||
mod dynamic_scene;
|
||||
|
@ -20,6 +27,7 @@ pub use scene_filter::*;
|
|||
pub use scene_loader::*;
|
||||
pub use scene_spawner::*;
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub mod prelude {
|
||||
#[doc(hidden)]
|
||||
pub use crate::{
|
||||
|
@ -31,6 +39,7 @@ pub mod prelude {
|
|||
use bevy_app::prelude::*;
|
||||
use bevy_asset::AssetApp;
|
||||
|
||||
/// Plugin that provides scene functionality to an [`App`].
|
||||
#[derive(Default)]
|
||||
pub struct ScenePlugin;
|
||||
|
||||
|
|
|
@ -15,10 +15,12 @@ use bevy_utils::HashMap;
|
|||
/// [`GlobalTransform`](bevy_transform::components::GlobalTransform) components)
|
||||
#[derive(Asset, TypePath, Debug)]
|
||||
pub struct Scene {
|
||||
/// The world of the scene, containing its entities and resources.
|
||||
pub world: World,
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
/// Creates a new scene with the given world.
|
||||
pub fn new(world: World) -> Self {
|
||||
Self { world }
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use bevy_utils::BoxedFuture;
|
|||
#[cfg(feature = "serialize")]
|
||||
use serde::de::DeserializeSeed;
|
||||
|
||||
/// [`AssetLoader`] for loading serialized Bevy scene files as [`DynamicScene`].
|
||||
#[derive(Debug)]
|
||||
pub struct SceneLoader {
|
||||
type_registry: TypeRegistryArc,
|
||||
|
|
|
@ -28,6 +28,7 @@ pub struct InstanceInfo {
|
|||
pub entity_map: HashMap<Entity, Entity>,
|
||||
}
|
||||
|
||||
/// Unique id identifying a scene instance.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub struct InstanceId(Uuid);
|
||||
|
||||
|
@ -37,6 +38,25 @@ impl InstanceId {
|
|||
}
|
||||
}
|
||||
|
||||
/// Handles spawning and despawning scenes in the world, either synchronously or batched through the [`scene_spawner_system`].
|
||||
///
|
||||
/// Synchronous methods: (Scene operations will take effect immediately)
|
||||
/// - [`spawn_dynamic_sync`](Self::spawn_dynamic_sync)
|
||||
/// - [`spawn_sync`](Self::spawn_sync)
|
||||
/// - [`despawn_sync`](Self::despawn_sync)
|
||||
/// - [`despawn_instance_sync`](Self::despawn_instance_sync)
|
||||
/// - [`update_spawned_scenes`](Self::update_spawned_scenes)
|
||||
/// - [`spawn_queued_scenes`](Self::spawn_queued_scenes)
|
||||
/// - [`despawn_queued_scenes`](Self::despawn_queued_scenes)
|
||||
/// - [`despawn_queued_instances`](Self::despawn_queued_instances)
|
||||
///
|
||||
/// Deferred methods: (Scene operations will be processed when the [`scene_spawner_system`] is run)
|
||||
/// - [`spawn_dynamic`](Self::spawn_dynamic)
|
||||
/// - [`spawn_dynamic_as_child`](Self::spawn_dynamic_as_child)
|
||||
/// - [`spawn`](Self::spawn)
|
||||
/// - [`spawn_as_child`](Self::spawn_as_child)
|
||||
/// - [`despawn`](Self::despawn)
|
||||
/// - [`despawn_instance`](Self::despawn_instance)
|
||||
#[derive(Default, Resource)]
|
||||
pub struct SceneSpawner {
|
||||
spawned_scenes: HashMap<AssetId<Scene>, Vec<InstanceId>>,
|
||||
|
@ -50,27 +70,50 @@ pub struct SceneSpawner {
|
|||
scenes_with_parent: Vec<(InstanceId, Entity)>,
|
||||
}
|
||||
|
||||
/// Errors that can occur when spawning a scene.
|
||||
#[derive(Error, Debug)]
|
||||
pub enum SceneSpawnError {
|
||||
/// Scene contains an unregistered component type.
|
||||
#[error("scene contains the unregistered component `{type_name}`. consider adding `#[reflect(Component)]` to your type")]
|
||||
UnregisteredComponent { type_name: String },
|
||||
UnregisteredComponent {
|
||||
/// Type of the unregistered component.
|
||||
type_name: String,
|
||||
},
|
||||
/// Scene contains an unregistered resource type.
|
||||
#[error("scene contains the unregistered resource `{type_name}`. consider adding `#[reflect(Resource)]` to your type")]
|
||||
UnregisteredResource { type_name: String },
|
||||
UnregisteredResource {
|
||||
/// Type of the unregistered resource.
|
||||
type_name: String,
|
||||
},
|
||||
/// Scene contains an unregistered type.
|
||||
#[error("scene contains the unregistered type `{type_name}`. consider registering the type using `app.register_type::<T>()`")]
|
||||
UnregisteredType { type_name: String },
|
||||
UnregisteredType {
|
||||
/// The unregistered type.
|
||||
type_name: String,
|
||||
},
|
||||
/// Dynamic scene with the given id does not exist.
|
||||
#[error("scene does not exist")]
|
||||
NonExistentScene { id: AssetId<DynamicScene> },
|
||||
NonExistentScene {
|
||||
/// Id of the non-existent dynamic scene.
|
||||
id: AssetId<DynamicScene>,
|
||||
},
|
||||
/// Scene with the given id does not exist.
|
||||
#[error("scene does not exist")]
|
||||
NonExistentRealScene { id: AssetId<Scene> },
|
||||
NonExistentRealScene {
|
||||
/// Id of the non-existent scene.
|
||||
id: AssetId<Scene>,
|
||||
},
|
||||
}
|
||||
|
||||
impl SceneSpawner {
|
||||
/// Schedule the spawn of a new instance of the provided dynamic scene.
|
||||
pub fn spawn_dynamic(&mut self, id: impl Into<AssetId<DynamicScene>>) -> InstanceId {
|
||||
let instance_id = InstanceId::new();
|
||||
self.dynamic_scenes_to_spawn.push((id.into(), instance_id));
|
||||
instance_id
|
||||
}
|
||||
|
||||
/// Schedule the spawn of a new instance of the provided dynamic scene as a child of `parent`.
|
||||
pub fn spawn_dynamic_as_child(
|
||||
&mut self,
|
||||
id: impl Into<AssetId<DynamicScene>>,
|
||||
|
@ -82,12 +125,14 @@ impl SceneSpawner {
|
|||
instance_id
|
||||
}
|
||||
|
||||
/// Schedule the spawn of a new instance of the provided scene.
|
||||
pub fn spawn(&mut self, id: impl Into<AssetId<Scene>>) -> InstanceId {
|
||||
let instance_id = InstanceId::new();
|
||||
self.scenes_to_spawn.push((id.into(), instance_id));
|
||||
instance_id
|
||||
}
|
||||
|
||||
/// Schedule the spawn of a new instance of the provided scene as a child of `parent`.
|
||||
pub fn spawn_as_child(&mut self, id: impl Into<AssetId<Scene>>, parent: Entity) -> InstanceId {
|
||||
let instance_id = InstanceId::new();
|
||||
self.scenes_to_spawn.push((id.into(), instance_id));
|
||||
|
@ -95,14 +140,17 @@ impl SceneSpawner {
|
|||
instance_id
|
||||
}
|
||||
|
||||
/// Schedule the despawn of all instances of the provided dynamic scene.
|
||||
pub fn despawn(&mut self, id: impl Into<AssetId<DynamicScene>>) {
|
||||
self.scenes_to_despawn.push(id.into());
|
||||
}
|
||||
|
||||
/// Schedule the despawn of a scene instance, removing all its entities from the world.
|
||||
pub fn despawn_instance(&mut self, instance_id: InstanceId) {
|
||||
self.instances_to_despawn.push(instance_id);
|
||||
}
|
||||
|
||||
/// Immediately despawns all instances of a dynamic scene.
|
||||
pub fn despawn_sync(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
|
@ -116,6 +164,7 @@ impl SceneSpawner {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Immediately despawns a scene instance, removing all its entities from the world.
|
||||
pub fn despawn_instance_sync(&mut self, world: &mut World, instance_id: &InstanceId) {
|
||||
if let Some(instance) = self.spawned_instances.remove(instance_id) {
|
||||
for &entity in instance.entity_map.values() {
|
||||
|
@ -124,6 +173,7 @@ impl SceneSpawner {
|
|||
}
|
||||
}
|
||||
|
||||
/// Immediately spawns a new instance of the provided dynamic scene.
|
||||
pub fn spawn_dynamic_sync(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
|
@ -153,6 +203,7 @@ impl SceneSpawner {
|
|||
})
|
||||
}
|
||||
|
||||
/// Immediately spawns a new instance of the provided scene.
|
||||
pub fn spawn_sync(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
|
@ -182,6 +233,9 @@ impl SceneSpawner {
|
|||
})
|
||||
}
|
||||
|
||||
/// Iterate through all instances of the provided scenes and update those immediately.
|
||||
///
|
||||
/// Useful for updating already spawned scene instances after their corresponding scene has been modified.
|
||||
pub fn update_spawned_scenes(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
|
@ -199,6 +253,7 @@ impl SceneSpawner {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Immediately despawns all scenes scheduled for despawn by despawning their instances.
|
||||
pub fn despawn_queued_scenes(&mut self, world: &mut World) -> Result<(), SceneSpawnError> {
|
||||
let scenes_to_despawn = std::mem::take(&mut self.scenes_to_despawn);
|
||||
|
||||
|
@ -208,6 +263,7 @@ impl SceneSpawner {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Immediately despawns all scene instances scheduled for despawn.
|
||||
pub fn despawn_queued_instances(&mut self, world: &mut World) {
|
||||
let instances_to_despawn = std::mem::take(&mut self.instances_to_despawn);
|
||||
|
||||
|
@ -216,6 +272,7 @@ impl SceneSpawner {
|
|||
}
|
||||
}
|
||||
|
||||
/// Immediately spawns all scenes scheduled for spawn.
|
||||
pub fn spawn_queued_scenes(&mut self, world: &mut World) -> Result<(), SceneSpawnError> {
|
||||
let scenes_to_spawn = std::mem::take(&mut self.dynamic_scenes_to_spawn);
|
||||
|
||||
|
@ -308,6 +365,7 @@ impl SceneSpawner {
|
|||
}
|
||||
}
|
||||
|
||||
/// System that handles scheduled scene instance spawning and despawning through a [`SceneSpawner`].
|
||||
pub fn scene_spawner_system(world: &mut World) {
|
||||
world.resource_scope(|world, mut scene_spawner: Mut<SceneSpawner>| {
|
||||
// remove any loading instances where parent is deleted
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! `serde` serialization and deserialization implementation for Bevy scenes.
|
||||
|
||||
use crate::{DynamicEntity, DynamicScene};
|
||||
use bevy_ecs::entity::Entity;
|
||||
use bevy_reflect::serde::{TypedReflectDeserializer, TypedReflectSerializer};
|
||||
|
@ -14,19 +16,70 @@ use serde::{
|
|||
};
|
||||
use std::fmt::Formatter;
|
||||
|
||||
/// Name of the serialized scene struct type.
|
||||
pub const SCENE_STRUCT: &str = "Scene";
|
||||
/// Name of the serialized resources field in a scene struct.
|
||||
pub const SCENE_RESOURCES: &str = "resources";
|
||||
/// Name of the serialized entities field in a scene struct.
|
||||
pub const SCENE_ENTITIES: &str = "entities";
|
||||
|
||||
/// Name of the serialized entity struct type.
|
||||
pub const ENTITY_STRUCT: &str = "Entity";
|
||||
/// Name of the serialized component field in an entity struct.
|
||||
pub const ENTITY_FIELD_COMPONENTS: &str = "components";
|
||||
|
||||
/// Handles serialization of a scene as a struct containing its entities and resources.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_scene::{serde::SceneSerializer, DynamicScene};
|
||||
/// # use bevy_ecs::{
|
||||
/// # prelude::{Component, World},
|
||||
/// # reflect::{AppTypeRegistry, ReflectComponent},
|
||||
/// # };
|
||||
/// # use bevy_reflect::Reflect;
|
||||
/// // Define an example component type.
|
||||
/// #[derive(Component, Reflect, Default)]
|
||||
/// #[reflect(Component)]
|
||||
/// struct MyComponent {
|
||||
/// foo: [usize; 3],
|
||||
/// bar: (f32, f32),
|
||||
/// baz: String,
|
||||
/// }
|
||||
///
|
||||
/// // Create our world, provide it with a type registry.
|
||||
/// // Normally, [`App`] handles providing the type registry.
|
||||
/// let mut world = World::new();
|
||||
/// let registry = AppTypeRegistry::default();
|
||||
/// {
|
||||
/// let mut registry = registry.write();
|
||||
/// // Register our component. Primitives and String are registered by default.
|
||||
/// // Sequence types are automatically handled.
|
||||
/// registry.register::<MyComponent>();
|
||||
/// }
|
||||
/// world.insert_resource(registry);
|
||||
/// world.spawn(MyComponent {
|
||||
/// foo: [1, 2, 3],
|
||||
/// bar: (1.3, 3.7),
|
||||
/// baz: String::from("test"),
|
||||
/// });
|
||||
///
|
||||
/// // Print out our serialized scene in the RON format.
|
||||
/// let registry = world.resource::<AppTypeRegistry>();
|
||||
/// let scene = DynamicScene::from_world(&world);
|
||||
/// let scene_serializer = SceneSerializer::new(&scene, ®istry.0);
|
||||
/// println!("{}", bevy_scene::serialize_ron(scene_serializer).unwrap());
|
||||
/// ```
|
||||
pub struct SceneSerializer<'a> {
|
||||
/// The scene to serialize.
|
||||
pub scene: &'a DynamicScene,
|
||||
/// Type registry in which the components and resources types used in the scene are registered.
|
||||
pub registry: &'a TypeRegistryArc,
|
||||
}
|
||||
|
||||
impl<'a> SceneSerializer<'a> {
|
||||
/// Creates a scene serializer.
|
||||
pub fn new(scene: &'a DynamicScene, registry: &'a TypeRegistryArc) -> Self {
|
||||
SceneSerializer { scene, registry }
|
||||
}
|
||||
|
@ -56,8 +109,11 @@ impl<'a> Serialize for SceneSerializer<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Handles serialization of multiple entities as a map of entity id to serialized entity.
|
||||
pub struct EntitiesSerializer<'a> {
|
||||
/// The entities to serialize.
|
||||
pub entities: &'a [DynamicEntity],
|
||||
/// Type registry in which the component types used by the entities are registered.
|
||||
pub registry: &'a TypeRegistryArc,
|
||||
}
|
||||
|
||||
|
@ -80,8 +136,11 @@ impl<'a> Serialize for EntitiesSerializer<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Handles entity serialization as a map of component type to component value.
|
||||
pub struct EntitySerializer<'a> {
|
||||
/// The entity to serialize.
|
||||
pub entity: &'a DynamicEntity,
|
||||
/// Type registry in which the component types used by the entity are registered.
|
||||
pub registry: &'a TypeRegistryArc,
|
||||
}
|
||||
|
||||
|
@ -102,8 +161,15 @@ impl<'a> Serialize for EntitySerializer<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Handles serializing a list of values with a unique type as a map of type to value.
|
||||
///
|
||||
/// Used to serialize scene resources in [`SceneSerializer`] and entity components in [`EntitySerializer`].
|
||||
/// Note that having several entries of the same type in `entries` will lead to an error when using the RON format and
|
||||
/// deserializing through [`SceneMapDeserializer`].
|
||||
pub struct SceneMapSerializer<'a> {
|
||||
/// List of boxed values of unique type to serialize.
|
||||
pub entries: &'a [Box<dyn Reflect>],
|
||||
/// Type registry in which the types used in `entries` are registered.
|
||||
pub registry: &'a TypeRegistryArc,
|
||||
}
|
||||
|
||||
|
@ -136,7 +202,9 @@ enum EntityField {
|
|||
Components,
|
||||
}
|
||||
|
||||
/// Handles scene deserialization.
|
||||
pub struct SceneDeserializer<'a> {
|
||||
/// Type registry in which the components and resources types used in the scene to deserialize are registered.
|
||||
pub type_registry: &'a TypeRegistry,
|
||||
}
|
||||
|
||||
|
@ -227,7 +295,9 @@ impl<'a, 'de> Visitor<'de> for SceneVisitor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Handles deserialization for a collection of entities.
|
||||
pub struct SceneEntitiesDeserializer<'a> {
|
||||
/// Type registry in which the component types used by the entities to deserialize are registered.
|
||||
pub type_registry: &'a TypeRegistry,
|
||||
}
|
||||
|
||||
|
@ -272,8 +342,11 @@ impl<'a, 'de> Visitor<'de> for SceneEntitiesVisitor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Handle deserialization of an entity and its components.
|
||||
pub struct SceneEntityDeserializer<'a> {
|
||||
/// Id of the deserialized entity.
|
||||
pub entity: Entity,
|
||||
/// Type registry in which the component types used by the entity to deserialize are registered.
|
||||
pub type_registry: &'a TypeRegistry,
|
||||
}
|
||||
|
||||
|
@ -352,7 +425,9 @@ impl<'a, 'de> Visitor<'de> for SceneEntityVisitor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Handles deserialization of a sequence of values with unique types.
|
||||
pub struct SceneMapDeserializer<'a> {
|
||||
/// Type registry in which the types of the values to deserialize are registered.
|
||||
pub registry: &'a TypeRegistry,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue