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:
Kanabenki 2023-10-01 19:54:19 +02:00 committed by GitHub
parent a1a81e5721
commit ec34fe01d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 164 additions and 7 deletions

View file

@ -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,
}

View file

@ -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>,
}

View file

@ -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;

View file

@ -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 }
}

View file

@ -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,

View file

@ -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

View file

@ -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, &registry.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,
}