Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - bevy::scene::Entity renamed to bevy::scene::DynamicEntity. #3448

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions crates/bevy_scene/src/dynamic_scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,46 @@ use bevy_ecs::{
use bevy_reflect::{Reflect, TypeRegistryArc, TypeUuid};
use serde::Serialize;

/// A collection of serializable dynamic entities, each with its own run-time defined set of components.
#[derive(Default, TypeUuid)]
#[uuid = "749479b1-fb8c-4ff8-a775-623aa76014f5"]
pub struct DynamicScene {
pub entities: Vec<Entity>,
pub entities: Vec<DynamicEntity>,
}

pub struct Entity {
/// A reflection-powered serializable representation of an entity and its components.
pub struct DynamicEntity {
/// The transiently unique identifier of a corresponding `Entity`.
pub entity: u32,
/// A vector of boxed components that belong to the given entity and
/// implement the `Reflect` trait.
pub components: Vec<Box<dyn Reflect>>,
}

impl DynamicScene {
/// Create a new dynamic scene from a given scene.
pub fn from_scene(scene: &Scene, type_registry: &TypeRegistryArc) -> Self {
Self::from_world(&scene.world, type_registry)
}

/// Create a new dynamic scene from a given world.
pub fn from_world(world: &World, type_registry: &TypeRegistryArc) -> Self {
let mut scene = DynamicScene::default();
let type_registry = type_registry.read();

for archetype in world.archetypes().iter() {
let entities_offset = scene.entities.len();

// Create a new dynamic entity for each entity of the given archetype
// and insert it into the dynamic scene.
for entity in archetype.entities() {
scene.entities.push(Entity {
scene.entities.push(DynamicEntity {
entity: entity.id(),
components: Vec::new(),
});
}

// Add each reflection-powered component to the entity it belongs to.
for component_id in archetype.components() {
let reflect_component = world
.components()
Expand All @@ -58,17 +70,27 @@ impl DynamicScene {
scene
}

/// Write the dynamic entities and their corresponding components to the given world.
///
/// This method will return a `SceneSpawnError` if either a type is not registered
/// or doesn't reflect the `Component` trait.
pub fn write_to_world(
&self,
world: &mut World,
entity_map: &mut EntityMap,
) -> Result<(), SceneSpawnError> {
let registry = world.get_resource::<TypeRegistryArc>().unwrap().clone();
let type_registry = registry.read();

for scene_entity in self.entities.iter() {
// Fetch the entity with the given entity id from the `entity_map`
// or spawn a new entity with a transiently unique id if there is
// no corresponding entry.
let entity = *entity_map
.entry(bevy_ecs::entity::Entity::new(scene_entity.entity))
.or_insert_with(|| world.spawn().id());

// Apply/ add each component to the given entity.
for component in scene_entity.components.iter() {
let registration = type_registry
.get_with_name(component.type_name())
Expand All @@ -81,6 +103,10 @@ impl DynamicScene {
type_name: component.type_name().to_string(),
}
})?;

// If the entity already has the given component attached,
// just apply the (possibly) new value, otherwise add the
// component to the entity.
if world
.entity(entity)
.contains_type_id(registration.type_id())
Expand All @@ -104,11 +130,13 @@ impl DynamicScene {
}

// TODO: move to AssetSaver when it is implemented
/// Serialize this dynamic scene into rust object notation (ron).
pub fn serialize_ron(&self, registry: &TypeRegistryArc) -> Result<String, ron::Error> {
serialize_ron(SceneSerializer::new(self, registry))
}
}

/// Serialize a given Rust data structure into rust object notation (ron).
pub fn serialize_ron<S>(serialize: S) -> Result<String, ron::Error>
where
S: Serialize,
Expand Down
12 changes: 6 additions & 6 deletions crates/bevy_scene/src/serde.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{DynamicScene, Entity};
use crate::{DynamicEntity, DynamicScene};
use anyhow::Result;
use bevy_reflect::{
serde::{ReflectDeserializer, ReflectSerializer},
Expand Down Expand Up @@ -38,7 +38,7 @@ impl<'a> Serialize for SceneSerializer<'a> {
}

pub struct EntitySerializer<'a> {
pub entity: &'a Entity,
pub entity: &'a DynamicEntity,
pub registry: &'a TypeRegistryArc,
}

Expand Down Expand Up @@ -105,7 +105,7 @@ struct SceneEntitySeqVisitor<'a> {
}

impl<'a, 'de> Visitor<'de> for SceneEntitySeqVisitor<'a> {
type Value = Vec<Entity>;
type Value = Vec<DynamicEntity>;

fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("list of entities")
Expand All @@ -131,7 +131,7 @@ pub struct SceneEntityDeserializer<'a> {
}

impl<'a, 'de> DeserializeSeed<'de> for SceneEntityDeserializer<'a> {
type Value = Entity;
type Value = DynamicEntity;

fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
Expand Down Expand Up @@ -163,7 +163,7 @@ struct SceneEntityVisitor<'a> {
}

impl<'a, 'de> Visitor<'de> for SceneEntityVisitor<'a> {
type Value = Entity;
type Value = DynamicEntity;

fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("entities")
Expand Down Expand Up @@ -202,7 +202,7 @@ impl<'a, 'de> Visitor<'de> for SceneEntityVisitor<'a> {
let components = components
.take()
.ok_or_else(|| Error::missing_field(ENTITY_FIELD_COMPONENTS))?;
Ok(Entity {
Ok(DynamicEntity {
entity: *entity,
components,
})
Expand Down