From ec34fe01d1d09d0cdde73e61ff7056c0a1e857d0 Mon Sep 17 00:00:00 2001 From: Kanabenki Date: Sun, 1 Oct 2023 19:54:19 +0200 Subject: [PATCH] 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. --- crates/bevy_scene/src/bundle.rs | 14 ++++- crates/bevy_scene/src/dynamic_scene.rs | 2 + crates/bevy_scene/src/lib.rs | 9 ++++ crates/bevy_scene/src/scene.rs | 2 + crates/bevy_scene/src/scene_loader.rs | 1 + crates/bevy_scene/src/scene_spawner.rs | 68 +++++++++++++++++++++-- crates/bevy_scene/src/serde.rs | 75 ++++++++++++++++++++++++++ 7 files changed, 164 insertions(+), 7 deletions(-) diff --git a/crates/bevy_scene/src/bundle.rs b/crates/bevy_scene/src/bundle.rs index 48112de710..e47e198728 100644 --- a/crates/bevy_scene/src/bundle.rs +++ b/crates/bevy_scene/src/bundle.rs @@ -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, + /// 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, + /// 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, } diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 8630d8e1dc..dee1e4ae0f 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -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>, + /// Entities contained in the dynamic scene. pub entities: Vec, } diff --git a/crates/bevy_scene/src/lib.rs b/crates/bevy_scene/src/lib.rs index 66d9d02043..4ca3c303c3 100644 --- a/crates/bevy_scene/src/lib.rs +++ b/crates/bevy_scene/src/lib.rs @@ -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; diff --git a/crates/bevy_scene/src/scene.rs b/crates/bevy_scene/src/scene.rs index 65b41ed2be..db9f7fae7d 100644 --- a/crates/bevy_scene/src/scene.rs +++ b/crates/bevy_scene/src/scene.rs @@ -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 } } diff --git a/crates/bevy_scene/src/scene_loader.rs b/crates/bevy_scene/src/scene_loader.rs index 3856601631..e86c358432 100644 --- a/crates/bevy_scene/src/scene_loader.rs +++ b/crates/bevy_scene/src/scene_loader.rs @@ -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, diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index ebb037afdc..c0f1bb5781 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -28,6 +28,7 @@ pub struct InstanceInfo { pub entity_map: HashMap, } +/// 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, Vec>, @@ -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::()`")] - 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 }, + NonExistentScene { + /// Id of the non-existent dynamic scene. + id: AssetId, + }, + /// Scene with the given id does not exist. #[error("scene does not exist")] - NonExistentRealScene { id: AssetId }, + NonExistentRealScene { + /// Id of the non-existent scene. + id: AssetId, + }, } impl SceneSpawner { + /// Schedule the spawn of a new instance of the provided dynamic scene. pub fn spawn_dynamic(&mut self, id: impl Into>) -> 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>, @@ -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>) -> 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>, 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>) { 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| { // remove any loading instances where parent is deleted diff --git a/crates/bevy_scene/src/serde.rs b/crates/bevy_scene/src/serde.rs index c91d8084ff..515728cae0 100644 --- a/crates/bevy_scene/src/serde.rs +++ b/crates/bevy_scene/src/serde.rs @@ -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::(); +/// } +/// 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::(); +/// 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], + /// 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, }